• Spring Security在登录验证中增加额外数据(如验证码)


      在使用Spring Security框架过程中,经常会有这样的需求,即在登录验证时,附带增加额外的数据,如验证码、用户类型等。下面将介绍如何实现。

      注:我的工程是在Spring Boot框架基础上的,使用xml方式配置的话请读者自行研究吧。

    • 实现自定义的WebAuthenticationDetails

      该类提供了获取用户登录时携带的额外信息的功能,默认实现WebAuthenticationDetails提供了remoteAddress与sessionId信息。开发者可以通过Authentication的getDetails()获取WebAuthenticationDetails。我们编写自定义类CustomWebAuthenticationDetails继承自WebAuthenticationDetails,添加我们关心的数据(以下是一个token字段)。

    package com.cgs.courses.service;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.security.web.authentication.WebAuthenticationDetails;
    
    public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {
        /**
         * 
         */
        private static final long serialVersionUID = 6975601077710753878L;
        private final String token;
    
        public CustomWebAuthenticationDetails(HttpServletRequest request) {
            super(request);
            token = request.getParameter("token");
        }
    
        public String getToken() {
            return token;
        }
    
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(super.toString()).append("; Token: ").append(this.getToken());
            return sb.toString();
        }
    }

       注:在登录页面,可将token字段放在form表单中,也可以直接加在url的参数中,进而把额外数据发送给后台。

    • 实现自定义的AuthenticationDetailsSource

      该接口用于在Spring Security登录过程中对用户的登录信息的详细信息进行填充,默认实现是WebAuthenticationDetailsSource,生成上面的默认实现WebAuthenticationDetails。我们编写类实现AuthenticationDetailsSource,用于生成上面自定义的CustomWebAuthenticationDetails。

    package com.cgs.courses.service;

    import javax.servlet.http.HttpServletRequest;

    import org.springframework.security.authentication.AuthenticationDetailsSource;
    import org.springframework.security.web.authentication.WebAuthenticationDetails;
    import org.springframework.stereotype.Component;

    @Component
    public class CustomAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {

        @Override
        public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
            return new CustomWebAuthenticationDetails(context);
        }
    }
    • 配置使用自定义的AuthenticationDetailsSource

      只要看这一句.formLogin().authenticationDetailsSource(authenticationDetailsSource)

        @Autowired
        private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource;
    
        protected void configure(HttpSecurity http) throws Exception {
            http
                .headers()
                    .cacheControl()
                    .contentTypeOptions()
                    .httpStrictTransportSecurity()
                    .xssProtection()
                    .and()
                .authorizeRequests()
                    .antMatchers(
                        "/css/**",
                        "/js/**")
                    .permitAll()
                    .antMatchers("/**")
                    .authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll()
                    .defaultSuccessUrl("/todo.html", true)
                    .authenticationDetailsSource(authenticationDetailsSource)
                .and()
                    .logout()
                    .logoutUrl("/logout")
                    .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .logoutSuccessUrl("/login")
                    .and()
                .csrf().disable();
        }
    • 实现自定义的AuthenticationProvider

      AuthenticationProvider提供登录验证处理逻辑,我们实现该接口编写自己的验证逻辑。

    package com.cgs.courses.service;
    
    import org.springframework.security.authentication.AuthenticationProvider;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.stereotype.Component;
    
    @Component
    public class CustomAuthenticationProvider implements AuthenticationProvider {
        
        @Override
        public Authentication authenticate(Authentication authentication) 
                throws AuthenticationException {
            CustomWebAuthenticationDetails details = (CustomWebAuthenticationDetails) authentication.getDetails();  // 如上面的介绍,这里通过authentication.getDetails()获取详细信息
            // System.out.println(details); details.getRemoteAddress(); details.getSessionId(); details.getToken();
    // 下面是验证逻辑,验证通过则返回UsernamePasswordAuthenticationToken,
    // 否则,可直接抛出错误(AuthenticationException的子类,在登录验证不通过重定向至登录页时可通过session.SPRING_SECURITY_LAST_EXCEPTION.message获取具体错误提示信息)
    if (验证通过) {
    return UsernamePasswordAuthenticationToken(省略参数);
    } else {
    throw new AuthenticationException的子类("你要显示的错误信息")
    }
    } @Override public boolean supports(Class<?> authentication) { return authentication.equals(UsernamePasswordAuthenticationToken.class); } }
    • 配置使用自定义的AuthenticationProvider
      @Autowired
        private AuthenticationProvider authenticationProvider;

      @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authenticationProvider); }
  • 相关阅读:
    Django学习【第5篇】:Django之ORM数据库操作注意细节
    Django学习【第5篇】:Django之ORM数据库操作
    Django学习【第4篇】:Django之模板继承
    Django学习【第3篇】:Django之模板语法
    Django学习【第2篇】:Django之反向解析
    Django学习【第1篇】:Django之MTV模型
    cookie和session
    Django 之 auth 模块
    Django 之 form表单
    中间件的流程图
  • 原文地址:https://www.cnblogs.com/phoenix-smile/p/5666686.html
Copyright © 2020-2023  润新知