当前位置: 首页 > news >正文

SpringSecurity如何实现前后端分离

前后端分离模式是指由前端控制页面路由,后端接口也不再返回html数据,而是直接返回业务数据,数据一般是JSON格式。Spring Security默认的表单登录方式,在未登录或登录成功时会发起页面重定向,在提交登录数据时,也不是JSON格式。要支持前后端分离模式,要对这些问题进行改造。

1. 认证信息改成JSON格式

Spring Security默认提供账号密码认证方式,具体实现是在UsernamePasswordAuthenticationFilter 中。因为是表单提交,所以Filter中用request.getParameter(this.usernameParameter) 来获取用户信息。当我们将数据改成JSON,并放入HTTP Body后,getParameter 就没法获取到信息。

要解决这个问题,就要新建Filter来替换UsernamePasswordAuthenticationFilter ,然后覆盖掉获取用户的方法。

1.1 新建JsonUsernamePasswordAuthenticationFilter

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import org.springframework.data.util.Pair;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;public class JsonUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {@Overridepublic Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)throws AuthenticationException {if (!request.getMethod().equals("POST")) {throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());}Pair<String, String> usernameAndPassword = obtainUsernameAndPassword(request);String username = usernameAndPassword.getFirst();username = (username != null) ? username.trim() : "";String password = usernameAndPassword.getSecond();password = (password != null) ? password : "";UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username,password);// Allow subclasses to set the "details" propertysetDetails(request, authRequest);return this.getAuthenticationManager().authenticate(authRequest);}@SneakyThrowsprivate Pair<String, String> obtainUsernameAndPassword(HttpServletRequest request) {JSONObject map = JSON.parseObject(request.getInputStream(), JSONObject.class);return Pair.of(map.getString(getUsernameParameter()), map.getString(getPasswordParameter()));}
}

1.2 新建JsonUsernamePasswordLoginConfigurer

注册Filter有两种方式,一给是直接调用httpSecurity的addFilterAt(Filter filter, Class<? extends Filter> atFilter) ,另一个是注册通过AbstractHttpConfigurer 来注册。我们选择第二种方式来注册Filter,因为AbstractHttpConfigurer 在初始化 UsernamePasswordAuthenticationFilter 的时候,会额外设置一些信息。新建一个自己的AbstractHttpConfigurer

import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;public final class JsonUsernamePasswordLoginConfigurer<H extends HttpSecurityBuilder<H>> extendsAbstractAuthenticationFilterConfigurer<H, JsonUsernamePasswordLoginConfigurer<H>, JsonUsernamePasswordAuthenticationFilter> {public JsonUsernamePasswordLoginConfigurer() {super(new JsonUsernamePasswordAuthenticationFilter(), null);}@Overrideprotected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {return new AntPathRequestMatcher(loginProcessingUrl, "POST");}
}

1.3 注册JJsonUsernamePasswordLoginConfigurer到HttpSecurity

这一步比较简单,直接关闭表单登录,然后注册我们自己的Filter。

http.formLogin().disable().apply(new JsonUsernamePasswordLoginConfigurer<>())

经过这三步,Spring Security就能识别JSON格式的用户信息。

2. 去掉重定向

有几个场景会触发Spring Security的重定向:

  1. 未登录,重定向到登录页面

  1. 登录验证成功,重定向到默认页面

  1. 退出登录,重定向到默认页面

我们要对这几个场景分别处理,给前端返回错误信息,而不是重定向。

2.1 未登录请求

未登录的请求会被AuthorizationFilter拦截,并抛出异常。异常被AuthenticationEntryPoint处理,默认会触发重定向到登录页。我们通过自定义AuthenticationEntryPoint来取消重定向行为,改为返回JSON信息。

http
// 1. 未登录的请求会被AuthorizationFilter拦截,并抛出异常。
.exceptionHandling(it -> it.authenticationEntryPoint((request, response, authException) -> {log.info("get exception {}", authException.getClass());String msg = "{\\"msg\\": \\"用户未登录\\"}";response.setStatus(HttpStatus.FORBIDDEN.value());response.setContentType(MediaType.APPLICATION_JSON_VALUE);PrintWriter writer = response.getWriter();writer.write(msg);writer.flush();writer.close();
}))

2.2 登录成功/失败

登录成功或失败后的行为由AuthenticationSuccessHandler 和AuthenticationFailureHandler 来控制。由于上面我们自定义了JsonUsernamePasswordLoginConfigurer ,所以要配置自定义Configurer 上的AuthenticationSuccessHandler 和AuthenticationFailureHandler 。

http.formLogin().disable().apply((SecurityConfigurerAdapter) new JsonUsernamePasswordLoginConfigurer<>().successHandler((request, response, authentication) -> {String msg = "{\\"msg\\": \\"登录成功\\"}";response.setStatus(HttpStatus.OK.value());response.setContentType(MediaType.APPLICATION_JSON_VALUE);PrintWriter writer = response.getWriter();writer.write(msg);writer.flush();writer.close();}).failureHandler((request, response, exception) -> {String msg = "{\\"msg\\": \\"用户名密码错误\\"}";response.setStatus(HttpStatus.UNAUTHORIZED.value());response.setContentType(MediaType.APPLICATION_JSON_VALUE);PrintWriter writer = response.getWriter();writer.write(msg);writer.flush();writer.close();}));

2.3 退出登录

// 退出登录
.logout(it -> it.logoutSuccessHandler((request, response, authentication) -> {String msg = "{\\"msg\\": \\"退出成功\\"}";response.setStatus(HttpStatus.OK.value());response.setContentType(MediaType.APPLICATION_JSON_VALUE);PrintWriter writer = response.getWriter();writer.write(msg);writer.flush();writer.close();}))

3. 最后处理CSRF校验

由于前端直接调用登录接口,跳过了获取登录页面的步骤,所以服务端没有机会将CSRF Token传给前段,所以要把POST /login接口的CSRF校验剔除掉。

http.csrf(it -> it.ignoringRequestMatchers("/login", "POST"))

相关文章:

SpringSecurity如何实现前后端分离

前后端分离模式是指由前端控制页面路由&#xff0c;后端接口也不再返回html数据&#xff0c;而是直接返回业务数据&#xff0c;数据一般是JSON格式。Spring Security默认的表单登录方式&#xff0c;在未登录或登录成功时会发起页面重定向&#xff0c;在提交登录数据时&#xff…...

为ubuntu 18.04添加蓝牙驱动

目录背景方法背景 从网上买的能直接插ubuntu 1804的usb蓝牙太少了&#xff0c;而且还贵。我就直接从JD下单的一个便宜的USB蓝牙&#xff0c;结果插上机器没有驱动起不来。我的PC是个3年前的老机器&#xff0c;实在是不想升级系统&#xff0c;于是捣鼓半天捣鼓好了&#xff0c;…...

Stable Diffusion Prompt用法

Stable Diffusion可以根据你输入的提示词&#xff08;prompt&#xff09;来绘制出想象中的画面。 1、正向提示词&#xff08;Prompt&#xff09;&#xff1a; 提高图像质量的prompt: prompt用途HDR, UHD, 64K(HDR、UHD、4K、8K和64K)这样的质量词可以带来巨大的差异提升照片…...

jenkins问题

目录 python 不是内部或外部命令&#xff0c;也不是可运行的程序 ‘cmd’ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 git 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 pywintypes.com_error: (-2147024891, ‘拒绝访问。’, None,…...

阅读笔记DeepAR: Probabilistic Forecasting with Autoregressive Recurrent Networks

zi,t∈Rz_{i,t}\in \mathbb{R}zi,t​∈R表示时间序列iii在ttt时刻的值。给一个连续时间段t∈[1,T]t\in [1, T]t∈[1,T]&#xff0c;将其划分为context window[1,t0)[1,t_0)[1,t0​)和prediction window[t0,T][t_0,T][t0​,T]。用context window的时间序列预测prediction window…...

01.Java的安装

1.JDK&JREJDK : Java SE Development Kit--Java开发工具JRE : Java Runtime Environment--Java运行环境Java编程&#xff0c;需要安装JDK;如果仅仅是运行一款Java程序则只需要运行JREJava的安装包分为两类&#xff1a;一类是JRE--是一个独立的Java运行环境&#xff1b; 一类…...

【C语言深度剖析】关键字(全)

文章目录一.存储类型关键字前言补充1&#xff1a;内存思考&#xff1a;补充2&#xff1a;变量与内存的关系补充3&#xff1a;变量的分类补充4&#xff1a;存储类补充5&#xff1a;删除数据是怎么删除的&#xff1f;1.auto2.register3.static4.extern基本用法:基本功能5.typedef…...

English Learning - L2 语音作业打卡 双元音 [aʊ] [əʊ] Day15 2023.3.7 周二

English Learning - L2 语音作业打卡 双元音 [aʊ] [əʊ] Day15 2023.3.7 周二&#x1f48c;发音小贴士&#xff1a;&#x1f48c;当日目标音发音规则/技巧:&#x1f36d; Part 1【热身练习】&#x1f36d; Part2【练习内容】&#x1f36d;【练习感受】&#x1f353;元音 /eɪ…...

记第一次面试的过程(C++)

说实话三月份上旬过得很充实&#xff0c;而且感觉蛮值&#xff0c;但还有不足的地方&#xff0c;今晚特地看完资料分析来复盘复盘。 时间还要回到3.2中午13.35&#xff08;别问我为什么那么准确&#xff0c;刚刚掏手机看的&#xff09;&#xff0c;我正在吃着饭看着王者荣耀的直…...

06 电力电子仿真 MATLAB/Simulink

文章目录01 单相半波整流电路02 单相全波整流电路&#xff08;子系统封装模块&#xff09;03 三相桥式整流电路&#xff08;三相模块与示波器使用&#xff09;04 相控与斩控交交调压&#xff08;THD计算&#xff09;05 Buck电路&#xff08;PWM实现与闭环反馈&#xff09;06 单…...

搞懂面向对象这五大概念,才算真正跨过初学者到开发者的“分水岭“

文章目录前言一、对象二、类三、面向对象程序设计的特点1. 封装2. 继承3. 多态前言 面向对象程序设计是在面向过程程序设计的基础上发展而来的&#xff0c;它比面向过程编程具有更强的灵活性和扩展性。面向对象程序设计也是一个程序员发展的 “分水岭”&#xff0c;很多的初学者…...

基于DelayQueue实现的延时队列

基于java中延时队列的实现该文章&#xff0c;我们这次主要是来实现基于DelayQueue实现的延时队列。 使用DelayQueue实现的延时队列的步骤&#xff1a; 定义一个继承了Delayed的类&#xff0c;定义其中的属性&#xff0c;并重写compareTo和getDelay两个方法创建一个Delayqueue…...

MATLAB实现层次分析法AHP及案例分析

层次分析法(Analytic Hierarchy Process, AHP) 1 模型背景 美国运筹学家匹兹堡大学教授Saaty在20世纪70年代初提出的一种层次权重决策分析方法。 层次分析法(Analytic Hierarchy Process, AHP)是一种定性和定量分析相结合的决策分析方法。 特点:用较少的定量信息使决策的…...

Vue 3.0 TypeScript支持

Vue CLI 提供内置的 TypeScript 工具支持。 #NPM 包中的官方声明 随着应用的增长&#xff0c;静态类型系统可以帮助防止许多潜在的运行时错误&#xff0c;这就是为什么 Vue 3 是用 TypeScript 编写的。这意味着在 Vue 中使用 TypeScript 不需要任何其他工具——它具有一流的公…...

STM8S系列基于IAR标准外设printf输出demo

STM8S系列基于IAR标准外设printf输出demo&#x1f4cc;STM8S/A标准外设库&#xff08;库版本V2.3.1&#xff09;&#x1f4cd;官网标准外设库&#xff1a;https://www.st.com/zh/embedded-software/stsw-stm8069.html ⛳注意事项 &#x1f6a9;在内存空间比较有限的情况下&am…...

PMP项目管理项目质量管理

目录1 项目质量管理概述2 规划质量管理3 管理质量4 控制质量1 项目质量管理概述 项目质量管理包括把组织的质量政策应用于规则、管理、控制项目和产品质量要求&#xff0c;以满足相关方目标的各个过程。项目质量管理还将以组织的名义支持过程的持续改进活动。 核心概念 质量是…...

前缀和总结

前缀和是一个常用的算法技巧,通常用于求解数组或序列的区间和。 具体来说,假设有一个长度为n的数组a,我们可以预处理出一个长度为n+1的前缀和数组s,其中s[i]表示原数组a前i个元素的和,即: s[i] = a[0] + a[1] + ... + a[i-1] 这样一来,对于任意的区间[l, r],我们可以…...

0109二分图-无向图-数据结构和算法(Java)

文章目录1 概念2 API3 分析和实现4 测试5 总结后记1 概念 二分图是一种能将所有结点分为两部分的图&#xff0c;其中图的每条边所连接的两个顶点都分别属于不同的部分。 2 API public classBipartiteBipartite(Graph G)预处理函数public booleanisBipartitle()是否是二分图pub…...

计算机网络题库---选择题刷题训练(100多道精品)

第一章 概述 1.下列四项内容中&#xff0c;不属于Internet&#xff08;因特网&#xff09;基本功能是___D_____。 A.电子邮件 B.文件传输 C.远程登录 D.实时监测控制 2.Internet是建立在____C_____协议集上的国际互联网络。 A.IPX B.NetBEUI C.TCP/IP …...

16、字符串生成器

目录 &#xff08;1&#xff09;append()方法 &#xff08;2&#xff09;insert(int offset, arg)方法 &#xff08;3&#xff09;delete(int start , int end)方法 创建成功的字符串对象&#xff0c;其长度是固定的&#xff0c;内容不能被改变和编译。虽然使用“”可以达到…...

苹果内购Java后端避坑指南:沙盒测试、凭据验证与订单防重的那些事儿

苹果内购Java后端避坑指南&#xff1a;沙盒测试、凭据验证与订单防重的那些事儿 第一次对接苹果应用内购&#xff08;IAP&#xff09;时&#xff0c;我以为按照官方文档走完流程就万事大吉了。直到凌晨三点收到服务器告警——重复充值、验证超时、沙盒环境漏测等问题接踵而至。…...

国际大牌入门之选

这些品牌是轻奢饰品界的常青树&#xff0c;设计经典&#xff0c;辨识度高&#xff0c;是很多人的入门首选。卡地亚 27%人推荐猎豹为图腾&#xff0c;工艺精湛&#xff0c;是轻奢界的经典与传奇。宝格丽 24%人推荐跃马徽记是其标志&#xff0c;珠宝设计性感矜贵&#xff0c;灵蛇…...

如何快速配置HomeAssistant格力空调本地控制组件:完整操作指南

如何快速配置HomeAssistant格力空调本地控制组件&#xff1a;完整操作指南 【免费下载链接】HomeAssistant-GreeClimateComponent Custom Gree climate component written in Python3 for Home Assistant. Controls ACs supporting the Gree protocol. 项目地址: https://git…...

华为新机散热“封神”:拆解仿生羽翼涡扇,看“小翅膀”如何颠覆手机温控

&#x1f393;作者简介&#xff1a;科技自媒体优质创作者 &#x1f310;个人主页&#xff1a;莱歌数字-CSDN博客 &#x1f48c;公众号&#xff1a;莱歌数字&#xff08;B站同名&#xff09; &#x1f4f1;个人微信&#xff1a;yanshanYH 211、985硕士&#xff0c;从业16年 从…...

Yep应用商店优化终极指南:提升App Store排名与下载量的10个策略

Yep应用商店优化终极指南&#xff1a;提升App Store排名与下载量的10个策略 【免费下载链接】Yep Meet Genius 项目地址: https://gitcode.com/gh_mirrors/ye/Yep Yep是一款主打社交互动的移动应用&#xff0c;通过优化App Store展示内容和用户体验&#xff0c;可以显著…...

OpenClaw隐私保护方案:ollama-QwQ-32B本地化数据处理流程

OpenClaw隐私保护方案&#xff1a;ollama-QwQ-32B本地化数据处理流程 1. 为什么需要本地化隐私保护方案 去年我在处理一份涉及客户隐私的市场分析报告时&#xff0c;遇到了一个棘手问题&#xff1a;当使用云端AI服务进行数据清洗和分析时&#xff0c;不得不将包含敏感字段的原…...

Word制表位全攻略:从菜鸟到高手,5分钟搞定专业文档排版

Word制表位全攻略&#xff1a;从菜鸟到高手&#xff0c;5分钟搞定专业文档排版 你是否曾经为了对齐文档中的文字而疯狂敲击空格键&#xff1f;或是花费大量时间调整表格边框却依然无法让数字完美对齐&#xff1f;这些困扰其实只需要掌握一个Word中的隐藏神器——制表位&#x…...

SLANeXt_wireless_safetensors:免费AI无线安全工具入门指南

SLANeXt_wireless_safetensors&#xff1a;免费AI无线安全工具入门指南 【免费下载链接】SLANeXt_wireless_safetensors 项目地址: https://ai.gitcode.com/paddlepaddle/SLANeXt_wireless_safetensors 导语&#xff1a;SLANeXt_wireless_safetensors作为一款免费的AI无…...

机器视觉中的坐标系转换:从像素到世界的无缝衔接

1. 机器视觉中的坐标系基础概念 第一次接触机器视觉时&#xff0c;最让我困惑的就是各种坐标系之间的关系。记得当时调试工业相机时&#xff0c;明明在图像上看到了目标物体&#xff0c;但机械臂就是抓不准位置。后来才发现&#xff0c;问题出在没有正确理解像素坐标系和世界坐…...

利用快马平台快速生成proteus仿真项目,十分钟搭建arduino温湿度监测原型

作为一名电子爱好者&#xff0c;最近在做一个温湿度监测的小项目。传统方式需要先在电脑上安装Proteus、Arduino IDE等一堆软件&#xff0c;配置起来特别麻烦。后来发现了InsCode(快马)平台&#xff0c;简直打开了新世界的大门——不用安装任何软件&#xff0c;直接在网页上就能…...