Springboot整合SpringSecurity:自定义用户认证

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,我也是第一次学习,若有不当之处,请各位大佬不吝赐教~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值