spring security配置自定义认证
spring security认证机制:
自定义认证类: 1.实现接口
AuthenticationProvider
,spring security内置的认证实现类DaoAuthenticationProvider
。
2.重写authenticate(Authentication authentication)
方法,实现认证逻辑。
spring security
的一般认证逻辑是:
- 首先将客户端传递的用户名和密码封装成一个
Authentication
对象作为authenticate()
方法的入参。 - 然后从
Authentication
对象中获取用户名,再使用定义的UserDetailesService
接口的loadUserByUsername(String name)
方法在存储中查询返回一个UserDetailes
对象(封装了用户名,密码,权限列表) - 找到后将
UserDetailes
对象和Authentication
对象中的密码做校对。 - 校对成功用户认证就成功了
- 最后将用户信息(含身份信息、细节信息、密码、权限等)封装成一个对象返回,参考
UsernamePasswordAuthenticationToken
对象。 - 最最后,会自动将这个对象交给系统
SecurityContextHolder
中(功能类似Session),以便后期随时取用
通过实现一个自定义的UserDetailesService
接口,我们可以定义从任何地方获取认证数据源,只需要将用户信息(用户名,密码,权限列表)包装成UserDetailes返回就行。
在配置中定义使用自定义的UserDetailesService
,如下:
@Autowired
private MyUserDetailService myUserDetailService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/*使用自定义的UserDetailesService*/
auth.userDetailsService(MyUserDetailService);
}
如果要重写认证逻辑则还需要自定义AuthenticationProvider
接口实现类,重写authenticate(Authentication authentication)
方法添加认证逻辑,重写supports()
方法返回true。
在配置中使用自定义的AuthenticationProvider
,如下
@Autowired
private MyAuthenticationProvide myAuthenticationProvide;
@Autowired
private MyUserDetailService userDetailService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/*使用自定义的UserDetailesService*/
auth.userDetailsService(MyUserDetailService);
/*使用自定义的authenticationProvider认证逻辑*/
auth.authenticationProvider(myAuthenticationProvide);
}
这里提供一个简单的认证逻辑实现:
@Component
public class MyAuthenticationProvide implements AuthenticationProvider {
@Autowired
private MyUserDetailService userDetailService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails userDetails = userDetailService.loadUserByUsername(username);
if(userDetails==null){
throw new BadCredentialsException("用户名不存在");
}
if(!password.equals(userDetails.getPassword())){
throw new BadCredentialsException("密码错误");
}
/*用户名密码认证成功*/
return new UsernamePasswordAuthenticationToken(userDetails,password,userDetails.getAuthorities());
}
@Override
public boolean supports(Class<?> aClass) {
return true;
}
}