千家信息网

Spring security怎么重写Filter实现json登录

发表于:2025-02-03 作者:千家信息网编辑
千家信息网最后更新 2025年02月03日,这篇文章主要介绍Spring security怎么重写Filter实现json登录,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!JSON登录上面演示的是一种原始的登录方案,如果
千家信息网最后更新 2025年02月03日Spring security怎么重写Filter实现json登录

这篇文章主要介绍Spring security怎么重写Filter实现json登录,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

JSON登录

上面演示的是一种原始的登录方案,如果想将用户名密码通过JSON的方式进行传递,则需要自定义相关过滤器,通过分析源码我们发现,默认的用户名密码提取在UsernamePasswordAuthenticationFilter过滤器中,部分源码如下:

public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {    public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";    public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";    private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;    private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;    private boolean postOnly = true;    public UsernamePasswordAuthenticationFilter() {        super(new AntPathRequestMatcher("/login", "POST"));    }    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {        if (postOnly && !request.getMethod().equals("POST")) {            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());        }        String username = obtainUsername(request);        String password = obtainPassword(request);        if (username == null) {            username = "";        }        if (password == null) {            password = "";        }        username = username.trim();        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);        // Allow subclasses to set the "details" property                setDetails(request, authRequest);        return this.getAuthenticationManager().authenticate(authRequest);    }    protected String obtainPassword(HttpServletRequest request) {        return request.getParameter(passwordParameter);    }    protected String obtainUsername(HttpServletRequest request) {        return request.getParameter(usernameParameter);    }        //...        //...}

从这里可以看到,默认的用户名/密码提取就是通过request中的getParameter来提取的,如果想使用JSON传递用户名密码,只需要将这个过滤器替换掉即可,自定义过滤器如下:

public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {        @Override    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {        if (request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE) || request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) {            ObjectMapper mapper = new ObjectMapper();            UsernamePasswordAuthenticationToken authRequest = null;            try (InputStream is = request.getInputStream()) {                Map authenticationBean = mapper.readValue(is, Map.class);                authRequest = new UsernamePasswordAuthenticationToken(authenticationBean.get("username"), authenticationBean.get("password"));            } catch (IOException e) {                e.printStackTrace();                authRequest = new UsernamePasswordAuthenticationToken("", "");            } finally {                setDetails(request, authRequest);                return this.getAuthenticationManager().authenticate(authRequest);            }        } else {            return super.attemptAuthentication(request, response);        }    }}

这里只是将用户名/密码的获取方案重新修正下,改为了从JSON中获取用户名密码,然后在SecurityConfig中作出如下修改:

@Overrideprotected void configure(HttpSecurity http) throws Exception {            http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().csrf().disable();            http.addFilterAt(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);}@BeanCustomAuthenticationFilter customAuthenticationFilter() throws Exception {            CustomAuthenticationFilter filter = new CustomAuthenticationFilter();            filter.setAuthenticationSuccessHandler(new AuthenticationSuccessHandler() {                @Override                public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {                    resp.setContentType("application/json;charset=utf-8");                    PrintWriter out = resp.getWriter();                    RespBean respBean = RespBean.ok("登录成功!");                    out.write(new ObjectMapper().writeValueAsString(respBean));                    out.flush();                    out.close();                }            });            filter.setAuthenticationFailureHandler(new AuthenticationFailureHandler() {                @Override                public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {                    resp.setContentype("application/json;charset=utf-8");                    PrintWriter out = resp.getWriter();                    RespBean respBean = RespBean.error("登录失败!");                    out.write(new ObjectMapper().writeValueAsString(respBean));                    out.flush();                    out.close();                }            });            filter.setAuthenticationManager(authenticationManagerBean());            return filter;        }

搞定~

Spring security5 使用json登录

public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {     @Override    @SneakyThrows(IOException.class) //lombok try catch    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {        if (request.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)) {            ObjectMapper mapper = new ObjectMapper();            Map map = mapper.readValue(request.getInputStream(), Map.class);            String username = map.get(super.getUsernameParameter());            String password = map.get(super.getPasswordParameter());            if (username == null) {                username = "";            }            if (password == null) {                password = "";            }            username = username.trim();            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(                    username, password);            setDetails(request, authRequest);            return this.getAuthenticationManager().authenticate(authRequest);        }        return super.attemptAuthentication(request, response);    }}
@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {     @Override    protected void configure(HttpSecurity http) throws Exception {       http.addFilterAt(usernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)    }      CustomUsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter() throws Exception {        CustomUsernamePasswordAuthenticationFilter filter = new CustomUsernamePasswordAuthenticationFilter();        filter.setAuthenticationManager(super.authenticationManagerBean());        filter.setFilterProcessesUrl(customSecurityProperties.getLoginUrl());        //处理登录成功        filter.setAuthenticationSuccessHandler(new AuthenticationSuccessHandler());        //处理登录失败        filter.setAuthenticationFailureHandler(new AuthenticationFailureHandler());        return filter;    }}

以上是"Spring security怎么重写Filter实现json登录"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

0