天天看點

spring secutiry密碼驗證的另一種解決辦法(薦)

最近在內建sping security 到spring boot中,看到大部分登陸驗證的代碼都這麼寫

@Service
public class CustomUserService implements UserDetailsService { //自定義UserDetailsService 接口

    @Autowired
    UserDao userDao;
    @Autowired
    PermissionDao permissionDao;

    public UserDetails loadUserByUsername(String username) {
        SysUser user = userDao.findByUserName(username);
        if (user != null) {
            List<Permission> permissions = permissionDao.findByAdminUserId(user.getId());
            List<GrantedAuthority> grantedAuthorities = new ArrayList <>();
            for (Permission permission : permissions) {
                if (permission != null && permission.getName()!=null) {

                GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName());
                grantedAuthorities.add(grantedAuthority);
                }
            }
            return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
        } else {
            throw new UsernameNotFoundException("admin: " + username + " do not exist!");
        }
    }

}

           

然後配置那時的代碼為:

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(urlUserService).passwordEncoder(new PasswordEncoder() {

            @Override
            public String encode(CharSequence rawPassword) {
                return MD5Util.encode((String) rawPassword);
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return encodedPassword.equals(MD5Util.encode((String) rawPassword));
            }
        });
    }

           

看到以上代碼,我就有個疑問了。

loadUserByUsername是為什麼要把使用者的權限也擷取了呢,如果密碼不正确,那擷取的權限也沒有用,浪費性能。

個人調試了一下代碼,發現登陸驗證時,确實會調用到loadUserByUsername。

那怎麼辦呢?如何解決。

經查,解決辦法如下;

1.不使用UserDetailsService,改為使用AbstractUserDetailsAuthenticationProvider

示例代碼如下:

public class MucAppAuthenticationProvider extends
        AbstractUserDetailsAuthenticationProvider {
    private static Logger logger = LoggerFactory.getLogger(AbstractUserDetailsAuthenticationProvider.class);

    @Autowired
    SecurityUserService securityUserService;

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails,
                                                  UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        //如果想做點額外的檢查,可以在這個方法裡處理,校驗不通時,直接抛異常即可
    }

    @Override
    protected UserDetails retrieveUser(String username,
                                       UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        //擷取使用者權限或密碼校驗
        return loadUserDetail(username);
    }

    
    
}

           

2.配置WebSecurityConfigurer改為如下:

@Bean
    AppAuthenticationProvider appAuthenticationProvider() { // 注冊UserDetailsService 的bean
        return new AppAuthenticationProvider();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth.authenticationProvider(appAuthenticationProvider());
    }
           

經測試,登陸驗證沒有發現任何問題