Spring Security登录接口兼容JSON格式登录实现示例

 更新时间:2024年01月17日 09:40:19   作者:YYAugenstern  
前后端分离中,前端和后端的数据交互通常是JSON格式,本文主要介绍了Spring Security登录接口兼容JSON格式登录实现示例,具有一定的参考价值,感兴趣的可以了解一下

1、概述

前后端分离中,前端和后端的数据交互通常是JSON格式,而Spring Security的登录接口默认支持的是form-data或者x-www-form-urlencoded的,如下所示:

那么如何让Spring Security的登录接口也支持JSON格式登录呢?请看下文分析 

2、自定义过滤器

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2024/1/13 9:30
 * @Description:
 */
public class MyUsernamePasswordAuthenticationFilter7007 extends UsernamePasswordAuthenticationFilter {

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (!HttpMethod.POST.name().equals(request.getMethod())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        String sessionCode = (String) request.getSession().getAttribute("code");
        if (MediaType.APPLICATION_JSON_VALUE.equals(request.getContentType()) || MediaType.APPLICATION_JSON_UTF8_VALUE.equals(request.getContentType())) {
            Map<String, String> loginData = new HashMap<>(16);
            try {
                loginData = new ObjectMapper().readValue(request.getInputStream(), Map.class);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                String paramCode = loginData.get("code");
                try {
                    checkCode(response,paramCode,sessionCode);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            String username = loginData.get(getUsernameParameter());
            String password = loginData.get(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);
        } else {
            try {
                checkCode(response,request.getParameter("code"),sessionCode);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return super.attemptAuthentication(request, response);
        }
    }

    /**
     * 检查验证码
     * @param response
     * @param paramCode
     * @param sessionCode
     */
    private void checkCode(HttpServletResponse response, String paramCode, String sessionCode) throws Exception {
        if (StringUtils.isBlank(paramCode)) {
            R r = R.error(ResponseEnum.VERIFY_CODE_IS_NULL.getCode(), ResponseEnum.VERIFY_CODE_IS_NULL.getMessage());
            response.setContentType("application/json;charset=utf-8");
            PrintWriter out = response.getWriter();
            out.write(new ObjectMapper().writeValueAsString(r));
            out.flush();
            out.close();
            return;
        }
        if (StringUtils.isBlank(sessionCode)) {
            R r = R.error(ResponseEnum.VERIFY_CODE_IS_EXPIRED.getCode(), ResponseEnum.VERIFY_CODE_IS_EXPIRED.getMessage());
            response.setContentType("application/json;charset=utf-8");
            PrintWriter out = response.getWriter();
            out.write(new ObjectMapper().writeValueAsString(r));
            out.flush();
            out.close();
            return;
        }
        if (!StringUtils.equals(paramCode.toLowerCase(), sessionCode.toLowerCase())) {
            R r = R.error(ResponseEnum.VERIFY_CODE_IS_NOT_MATCH.getCode(), ResponseEnum.VERIFY_CODE_IS_NOT_MATCH.getMessage());
            response.setContentType("application/json;charset=utf-8");
            PrintWriter out = response.getWriter();
            out.write(new ObjectMapper().writeValueAsString(r));
            out.flush();
            out.close();
            return;
        }
    }
}

3、配置类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2024/1/11 21:50
 * @Description: Spring Security配置类
 */
@Configuration
public class MyWebSecurityConfigurerAdapter7007 extends WebSecurityConfigurerAdapter {

    @Resource
    private MyAuthenticationSuccessHandler7007 successHandler;
    @Resource
    private MyAuthenticationFailureHandler7007 failureHandler;
    @Resource
    private MyLogoutSuccessHandler7007 logoutSuccessHandler;
    @Resource
    private MyAuthenticationEntryPoint7007 authenticationEntryPoint;
    @Resource
    private MyAccessDeniedHandler7007 accessDeniedHandler;
    @Resource
    private UserDetailsService userDetailsServiceImpl;

    /**
     * 密码加密器
     *
     * @return
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    /**
     * 定义基于MyBatis-Plus的用户
     *
     * @return
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsServiceImpl);
    }

    /**
     * 角色继承
     *
     * @return
     */
    @Bean
    protected RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_admin > ROLE_dba");

        return roleHierarchy;
    }

    @Bean
    public MyUsernamePasswordAuthenticationFilter7007 usernamePasswordAuthenticationFilter() throws Exception {
        MyUsernamePasswordAuthenticationFilter7007 usernamePasswordAuthenticationFilter = new MyUsernamePasswordAuthenticationFilter7007();
        usernamePasswordAuthenticationFilter.setFilterProcessesUrl("/login");
        usernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
        // 登录成功回调
        usernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(successHandler);
        // 登录失败回调
        usernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(failureHandler);
        return usernamePasswordAuthenticationFilter;

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/dba/**").hasRole("dba")
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/helloWorld", "/verifyCode/getVerifyCode")
                .permitAll()
                .anyRequest()
                .authenticated()

                .and()

                /**
                 * 注销登录回调
                 */
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler(logoutSuccessHandler)
                .permitAll()

                .and()

                .csrf()
                .disable()

                /**
                 * 未认证 & 权限不足回调
                 */
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler);
        http.addFilterAfter(usernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

}

4、测试

到此这篇关于Spring Security登录接口兼容JSON格式登录实现示例的文章就介绍到这了,更多相关Spring Security登录接口兼容JSON内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

您可能感兴趣的文章:

相关文章

  • Applet小应用程序开发简介

    Applet小应用程序开发简介

    Applet小应用程序开发简介 ,用java开发的小程序,需要的朋友可以参考下
    2012-09-09
  • Springboot自动装配之注入DispatcherServlet的实现方法

    Springboot自动装配之注入DispatcherServlet的实现方法

    这篇文章主要介绍了Springboot自动装配之注入DispatcherServlet,Springboot向外界提供web服务,底层依赖了springframework中的web模块来实现,那么springboot在什么时机向容器注入DispatcherServlet这个核心类的呢?带着这个问题一起通过本文学习吧
    2022-05-05
  • 带你轻松搞定Java面向对象的编程--数组,集合框架

    带你轻松搞定Java面向对象的编程--数组,集合框架

    Java是面向对象的高级编程语言,类和对象是 Java程序的构成核心。围绕着Java类和Java对象,有三大基本特性:封装是Java 类的编写规范、继承是类与类之间联系的一种形式、而多态为系统组件或模块之间解耦提供了解决方案
    2021-06-06
  • Java使用Hutool执行日期的加法和减法操作方法

    Java使用Hutool执行日期的加法和减法操作方法

    使用Hutool进行日期的加法和减法操作,可以使用`DateUtil.offsetXXX()`方法来实现,这些方法会返回一个新的日期,而不是在原日期上进行修改,本文给大家介绍Java使用Hutool执行日期的加法和减法操作方法,感兴趣的朋友一起看看吧
    2023-11-11
  • SpringBoot(JAVA)整合微信公众号消息推送完整步骤(文本、图片/视频推送)

    SpringBoot(JAVA)整合微信公众号消息推送完整步骤(文本、图片/视频推送)

    微信公众号消息推送包括文本推送和图文/视频推送两类,文本推送通过模板消息或自定义消息实现,而图文/视频推送需先上传素材至临时/永久素材库,再上传图文消息,最后进行消息推送,文中将实现的方法介绍的非常详细,需要的朋友可以参考下
    2024-09-09
  • java中实现对象排序的两种方法(Comparable,Comparator)

    java中实现对象排序的两种方法(Comparable,Comparator)

    这篇文章主要给大家介绍了关于java中实现对象排序的两种方法,一种是实现Comparable进行排序,另一种是实现Comparator进行排序,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • Java如何利用Mybatis进行数据权限控制详解

    Java如何利用Mybatis进行数据权限控制详解

    这篇文章主要介绍了Java如何利用Mybatis进行数据权限控制详解,数据权限控制最终的效果是会要求在同一个数据请求方法中,根据不同的权限返回不同的数据集,而且无需并且不能由研发编码控制。,需要的朋友可以参考下
    2019-06-06
  • jackson 如何将实体转json json字符串转实体

    jackson 如何将实体转json json字符串转实体

    这篇文章主要介绍了jackson 实现将实体转json json字符串转实体,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Springboot单元测试无法读取配置文件的解决方案

    Springboot单元测试无法读取配置文件的解决方案

    这篇文章主要介绍了Springboot单元测试无法读取配置文件的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java构造函数通透理解篇

    Java构造函数通透理解篇

    这篇文章主要介绍了Java构造函数,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09

最新评论