美文网首页
Spring Security 登录使用body参数手机号+验证

Spring Security 登录使用body参数手机号+验证

作者: 光芒121 | 来源:发表于2022-03-07 17:42 被阅读0次

    Spring Security 默认的formLogin登录传参是2个默认的字段,那就是username、password,并且也不是json格式,很多时候我们的业务使用都是phone和code字段,并且是接收对象,那么这时候就要重写相关的类来达到我们的效果了。


    默认的 login 定义的参数源码

    我们从源码中可以看到,默认的security登录帮我们实现了 "/login" 方法,也就是 UsernamePasswordAuthenticationFilter 类中定义的参数也都帮我们设置好了,所以我们传参时候想要其他格式的就得去重写 AbstractAuthenticationProcessingFilter 类去实现我们自己的名字和字段格式

    Security配置类

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        private final RequestCallbackHandler handler;
        private final LoginConfigurerAdapter adapter;
    
        public SecurityConfig(RequestCallbackHandler handler, LoginConfigurerAdapter adapter) {
            this.handler = handler;
            this.adapter = adapter;
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            //添加转码
            CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
            encodingFilter.setEncoding("UTF-8");
            encodingFilter.setForceEncoding(true);
            http.addFilterBefore(encodingFilter, CsrfFilter.class);
            //关闭跨域请求
            http.csrf().disable();
            http.authorizeRequests()
                    .antMatchers("/my/login").permitAll()
                    //登录之外的都需要进行验证
                    .anyRequest().authenticated()
                    .and().apply(adapter)
                    .and()
                    .exceptionHandling()
                    //没有登录回调
                    .authenticationEntryPoint(handler);
        }
    }
    

    重点设置接收body参数的地方:

    public class LoginProcessingFilter extends AbstractAuthenticationProcessingFilter {
    
        //把你们的登录地址写在此处 “/my/login” 等随意登录名字
        private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER =
                new AntPathRequestMatcher("/my/login", "POST");
    
        protected LoginProcessingFilter() {
            super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
        }
    
        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
            if (!request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException("不支持身份验证方法:" + request.getMethod());
            }
            String bodyString = getBodyString(request);
            String phone = null;
            String code = null;
            if (!StringUtils.isBlank(bodyString)) {
                //json转 LoginUserLoginVO 对象
                Gson gson = new Gson();
                LoginUserVO loginUserVO = gson.fromJson(bodyString, LoginUserVO.class);
                if (loginUserVO != null) {
                    //获取传递的手机号
                    phone = loginUserVO.getPhone();
                    //获取传递的验证码
                    code = loginUserVO.getCode();
                }
            }
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(phone, code);
            return this.getAuthenticationManager().authenticate(authenticationToken);
        }
    
        /**
         * 接收传递的jsonBody类型的参数
         */
        public String getBodyString(HttpServletRequest request) throws IOException {
            StringBuilder sb = new StringBuilder();
            InputStream inputStream = null;
            BufferedReader reader = null;
            try {
                inputStream = request.getInputStream();
                reader = new BufferedReader(
                        new InputStreamReader(inputStream, StandardCharsets.UTF_8));
    
                char[] bodyCharBuffer = new char[1024];
                int len = 0;
                while ((len = reader.read(bodyCharBuffer)) != -1) {
                    sb.append(new String(bodyCharBuffer, 0, len));
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return sb.toString();
        }
    }
    

    手机号和验证码逻辑判断处:

    public class LoginAuthenticationProvider implements AuthenticationProvider {
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            //用户名、手机号
            String phone = (String) authentication.getPrincipal();
            //密码、验证码
            String code = (String) authentication.getCredentials();
            if (StringUtils.isBlank(phone)) {
                throw new UsernameNotFoundException("手机号不能为空");
            }
            if (!phone.equals("123")) {    //正常去查询数据库
                throw new UsernameNotFoundException("用户不存在");
            }
            if (StringUtils.isBlank(code) || !code.equals("123456")) {
                throw new BadCredentialsException("验证码不正确");
            }
            return new UsernamePasswordAuthenticationToken(phone, code, null);
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return true;
        }
    }
    
    请求登录接口时候传递json对象格式

    相关文章

      网友评论

          本文标题:Spring Security 登录使用body参数手机号+验证

          本文链接:https://www.haomeiwen.com/subject/tgsarrtx.html