文章目录
1 引言
SpringSecurity可以在配置文件中,配置用户名、密码内存读取并校验;但我们现在连接mysql数据库,然后从数据库中读取用户信息,并自定义校验。
2 数据库表
这是一张随意写的用户表(MySQL),
role表示用户角色,1-管理员,2-普通用户。
3 SpringSecurity的配置文件
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
private final MyAuthenticationFailureHandler myAuthenticationFailureHandler;
private final MyAuthenticationProvider myAuthenticationProvider; // 自定义登录校验
@Autowired
public WebSecurityConfig(MyAuthenticationSuccessHandler myAuthenticationSuccessHandler, MyAuthenticationFailureHandler myAuthenticationFailureHandler, MyAuthenticationProvider myAuthenticationProvider) {
this.myAuthenticationSuccessHandler = myAuthenticationSuccessHandler;
this.myAuthenticationFailureHandler = myAuthenticationFailureHandler;
this.myAuthenticationProvider = myAuthenticationProvider;
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("static/admin/**");
}
// 授权
@Override
protected void configure(HttpSecurity http) throws Exception {
// 暂时关掉csrf跨域拦截
http.csrf().disable();
// login页面所有人可以访问
http.authorizeRequests()
.antMatchers("/admin/login").permitAll()
.antMatchers("/admin/index.html").hasRole("ADMIN")
.and()
.formLogin()
.successHandler(myAuthenticationSuccessHandler)
.failureHandler(myAuthenticationFailureHandler)
.and()
.formLogin()
.loginPage("/admin/login").loginProcessingUrl("/admin/toLogin");
}
// 认证
// There is no PasswordEncoder mapped for the id "null"
// 密码没被加密会报错~
// 在 spring security 5.0+ 中新增了很多密码加密到方法~
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(myAuthenticationProvider);
}
}
auth.authenticationProvider(myAuthenticationProvider);
将用户认证指定到我们自己写的MyAuthenticationProvider.java
4 MyAuthenticationProvider实现
/**
* Spring security 自定义登录校验
*/
@Component("MyAuthenticationProvider")
public class MyAuthenticationProvider implements AuthenticationProvider {
private UserService userService; // 查询用户信息的service接口
@Autowired
public MyAuthenticationProvider(UserService userService) {
this.userService = userService;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
// 通过用户名去数据库里查数据
UserDomain user = userService.getUserInfoByName(username);
// 登录校验
if (user == null) {
throw new UsernameNotFoundException("找不到用户名");
}
if (!user.getPassword().equals(password)) {
throw new BadCredentialsException("密码错误");
}
// 根据角色授予权限
String[] roles;
if(user.getRole() == 1) // 1-管理员,授予ADMIN、USER
roles = new String[]{"ROLE_ADMIN", "ROLE_USER"};
else if(user.getRole() == 2) // 2-用户,授予USER
roles = new String[]{"ROLE_USER"};
else
return null; // 没有角色授权失败
Collection<GrantedAuthority> authorities = getAuthorities(roles);
return new UsernamePasswordAuthenticationToken(user, user.getPassword(),
authorities);
}
/**
* 是否支持处理当前Authentication对象类似
*/
@Override
public boolean supports(Class<?> aClass) {
return UsernamePasswordAuthenticationToken.class.equals(aClass);
}
/**
* 返回权限集合
* @param roles 权限数组
* @return 权限集合
*/
private Collection<GrantedAuthority> getAuthorities(String[] roles) {
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
for(String role: roles){
// 角色必须要以"ROLE_"开头
SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role);
grantedAuthorities.add(grantedAuthority);
}
return grantedAuthorities;
}
}
可以看到认证的过程分为三个部分:
4.1 从数据库里拿用户数据
// 通过用户名去数据库里查数据
UserDomain user = userService.getUserInfoByName(username);
这部分的具体代码就粘了,比较简单。
4.2 校验用户名与密码
// 登录校验
if (user == null) {
throw new UsernameNotFoundException("找不到用户名");
}
if (!user.getPassword().equals(password)) {
throw new BadCredentialsException("密码错误, 请重新尝试");
}
4.3 授予角色权限
// 根据角色授予权限
String[] roles;
if(user.getRole() == 1) // 1-管理员,授予ADMIN、USER
roles = new String[]{"ROLE_ADMIN", "ROLE_USER"};
else if(user.getRole() == 2) // 2-用户,授予USER
roles = new String[]{"ROLE_USER"};
else
return null; // 没有角色授权失败
user.getRole()就是从该user对象中拿到role属性的值,1-管理员,2-普通用户。
最后我写了一个getAuthorities
,返回权限集合,放入UsernamePasswordAuthenticationToken()
这样就完成了自定义用户名与密码的校验!
5 测试
用postman测试
6 写在最后
对于Springboot整合SpringSecurity,我也是第一次学习,若有不当之处,请各位大佬不吝赐教~