Spring Security——"复杂"验证逻辑的实现

最近在复习spring security,随手写下这个文章,以方便自己记忆。本文将粗略介绍如何实现复杂验证逻 辑,以及介绍一部分源码。适合小白、中白看,需要之前对spring security有那么一丢丢的认识。我们将实现以下场景:
1)使用用户名、密码、手机号、暗号进行登陆,其中用户名、密码、手机号是用户注册时填写的,暗号是论坛的暗号“宫保鸡丁”。若登陆失败达到3次,该用户名对应的用户将锁定。
先说说我们的思路:
首先一个很自然的想法,就是我们提供一个过滤器对手机号、暗号进行验证,该过滤器在原生的用户名密码认证逻辑之前,只有这两个认证都通过后,认证流程才完成。
但是本文没有采用这种方式,因为这个过滤器filter对用户名手机号进行验证,这个验证逻辑就怕我们写得不够缜密(我还得去看原生的源码DaoAuthenticationProvider的authenticate方法,来写出缜密的认证流程!!),而且白白读多了一次数据库(读手机号),何不利用后面原生的用户名密码认证逻辑??——方案如下:暗号利用filter验证(因为不涉及用户信息),用户名、密码、手机号验证通过spring的认证框架AuthenticationProvider。
接下来我们开动改造啦!!
卖资源啦,本文对应工程请在https://download.csdn.net/download/xiaxuepiaopiao/12022396下载!
1)拓展原生的WebAuthenticationDetails,让认证的元素增加telephone参数。
该类提供了获取用户登录时携带的额外信息的功能,默认实现WebAuthenticationDetails提供了remoteAddress与sessionId信息。开发者可以通过Authentication的getDetails()获取WebAuthenticationDetails。我们编写自定义类CustomWebAuthenticationDetails继承自WebAuthenticationDetails,添加我们关心的数据。

public class WebAuthenticationDetails implements Serializable {
   
	private static final long serialVersionUID = 510L;
	private final String remoteAddress;
	private final String sessionId;
	...
}

我们提供如下CustomWebAuthenticationDetails

@Getter
public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {
   
    private final String telephone;
    public CustomWebAuthenticationDetails(HttpServletRequest request) {
   
        super(request);
        telephone = request.getParameter("telephone");
    }
}

telephone = request.getParameter(“telephone”)可以获得提交的表单中的telephone参数
2)提供自定义AuthenticationDetailsSource,该组件使用1)提供的WebAuthenticationDetails

@Component
public class CustomAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
   
    @Override
    public WebAuthenticationDetails buildDetails(HttpServletRequest httpServletRequest) {
   
        return new CustomWebAuthenticationDetails(httpServletRequest);
    }
}

该AuthenticationDetailsSource在spring security配置WebSecurityConfig中被调用,表示使用该组件:
@EnableWebSecurity

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
   
	...
    @Autowired
    private CustomAuthenticationDetailsSource customAuthenticationDetailsSource;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
   

    String[] permitUris = {
   "/css/**", "/js/**", "/login_result", "/anyone/**",
                "/login", "/userlogin**", "/UserLoginRegistry/**", "/index", "/static/**",
        "/api/conf","/registry","/indexA","/images/**","/manage**", "/login_code"};

    http.csrf().disable();
    http
        // 添加暗号校验filter,在默认校验器之前
        .addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
        .authorizeRequests()
        .antMatchers(permitUris).permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin()
        .loginPage("/login")
        .loginProcessingUrl("/userlogin") // 表示拦截到的路劲为/userlogin时,进入登录认证环节
        .successHandler(authenticationSuccessHandler) // 认证成功后逻辑
        .failureHandler(authenticationFailureHandler) // 认证失败后逻辑
        .authenticationDetailsSource(customAuthenticationDetailsSource); // 提供认证额外参数的能力

    }
}

3)定制AuthenticationProvider,拓展用户名密码验证模式为用户名密码手机号验证模式。
默认实现为DaoAuthenticationProvider,该类拓展了抽象类AbstractUserDetailsAuthenticationProvider。抽象类核心验证逻辑为public Authentication authenticate(Authentication authentication)。阅读源码,可知验证过程分三个阶段:preAuthenticationChecks、additionalAuthenticationChecks和postAuthenticationChec

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值