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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

您可能感兴趣的文章:

相关文章

  • Java建造者模式构建复杂对象的最佳实践

    Java建造者模式构建复杂对象的最佳实践

    建造者模式,是一种对象构建模式 它可以将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现的对象。本文将通过示例讲解建造者模式,需要的可以参考一下
    2023-04-04
  • 详解Java排序算法中的冒泡和选择排序

    详解Java排序算法中的冒泡和选择排序

    这篇文章主要给大家介绍了Java排序算法中的冒泡排序和选择排序,文中有详细的图文解释和代码示例,对我们学习Java算法有一定的帮助,感兴趣的同学可以参考阅读下
    2023-06-06
  • java使用jna调用c#中dll的方法详解

    java使用jna调用c#中dll的方法详解

    前一段时间接了个项目,需要用到第三方提供的C#编写的dll,本身项目是java语言,所以便有了下面这篇文章,本文给大家介绍了关于java中如何使用jna调用c#中dll的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-09-09
  • JpaRepository如何实现增删改查并进行单元测试

    JpaRepository如何实现增删改查并进行单元测试

    这篇文章主要介绍了JpaRepository如何实现增删改查并进行单元测试,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • java string 转date方法如何实现

    java string 转date方法如何实现

    在开发应用中经常会使用到java string 转date这种不是很常见的做法,本文将以此问题提供详细解决方案,需要了解的朋友可以参考下
    2012-11-11
  • IDEA 2022最新激活码注册码超详细教程(亲测激活有效)

    IDEA 2022最新激活码注册码超详细教程(亲测激活有效)

    这篇文章主要介绍了IDEA 2022最新激活码超详细教程(亲测激活至2099年),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • java eclipse 中文件的上传和下载示例解析

    java eclipse 中文件的上传和下载示例解析

    这篇文章主要介绍了eclipse java中文件的上传和下载示例解析,文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的。对此感兴趣的小伙伴可以了解一下
    2020-07-07
  • java 创建线程的几种方式

    java 创建线程的几种方式

    本文主要介绍了java中创建线程的几种方式。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • java 实现线程同步的方式有哪些

    java 实现线程同步的方式有哪些

    当使用多个线程来访问同一个数据时,非常容易出现线程安全问题,所以我们用同步机制来解决这些问题,本文将详细介绍,需要的朋友可以参考下
    2012-11-11
  • Java对象数组定义与用法详解

    Java对象数组定义与用法详解

    这篇文章主要介绍了Java对象数组定义与用法,结合实例形式分析了java对象数组的概念、功能、定义与使用方法,需要的朋友可以参考下
    2019-08-08

最新评论