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的重定向:
未登录,重定向到登录页面
登录验证成功,重定向到默认页面
退出登录,重定向到默认页面
我们要对这几个场景分别处理,给前端返回错误信息,而不是重定向。
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如何实现前后端分离
前后端分离模式是指由前端控制页面路由,后端接口也不再返回html数据,而是直接返回业务数据,数据一般是JSON格式。Spring Security默认的表单登录方式,在未登录或登录成功时会发起页面重定向,在提交登录数据时ÿ…...
为ubuntu 18.04添加蓝牙驱动
目录背景方法背景 从网上买的能直接插ubuntu 1804的usb蓝牙太少了,而且还贵。我就直接从JD下单的一个便宜的USB蓝牙,结果插上机器没有驱动起不来。我的PC是个3年前的老机器,实在是不想升级系统,于是捣鼓半天捣鼓好了,…...
Stable Diffusion Prompt用法
Stable Diffusion可以根据你输入的提示词(prompt)来绘制出想象中的画面。 1、正向提示词(Prompt): 提高图像质量的prompt: prompt用途HDR, UHD, 64K(HDR、UHD、4K、8K和64K)这样的质量词可以带来巨大的差异提升照片…...
jenkins问题
目录 python 不是内部或外部命令,也不是可运行的程序 ‘cmd’ 不是内部或外部命令,也不是可运行的程序或批处理文件。 git 不是内部或外部命令,也不是可运行的程序或批处理文件。 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],将其划分为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编程,需要安装JDK;如果仅仅是运行一款Java程序则只需要运行JREJava的安装包分为两类:一类是JRE--是一个独立的Java运行环境; 一类…...
【C语言深度剖析】关键字(全)
文章目录一.存储类型关键字前言补充1:内存思考:补充2:变量与内存的关系补充3:变量的分类补充4:存储类补充5:删除数据是怎么删除的?1.auto2.register3.static4.extern基本用法:基本功能5.typedef…...
English Learning - L2 语音作业打卡 双元音 [aʊ] [əʊ] Day15 2023.3.7 周二
English Learning - L2 语音作业打卡 双元音 [aʊ] [əʊ] Day15 2023.3.7 周二💌发音小贴士:💌当日目标音发音规则/技巧:🍭 Part 1【热身练习】🍭 Part2【练习内容】🍭【练习感受】🍓元音 /eɪ…...
记第一次面试的过程(C++)
说实话三月份上旬过得很充实,而且感觉蛮值,但还有不足的地方,今晚特地看完资料分析来复盘复盘。 时间还要回到3.2中午13.35(别问我为什么那么准确,刚刚掏手机看的),我正在吃着饭看着王者荣耀的直…...
06 电力电子仿真 MATLAB/Simulink
文章目录01 单相半波整流电路02 单相全波整流电路(子系统封装模块)03 三相桥式整流电路(三相模块与示波器使用)04 相控与斩控交交调压(THD计算)05 Buck电路(PWM实现与闭环反馈)06 单…...
搞懂面向对象这五大概念,才算真正跨过初学者到开发者的“分水岭“
文章目录前言一、对象二、类三、面向对象程序设计的特点1. 封装2. 继承3. 多态前言 面向对象程序设计是在面向过程程序设计的基础上发展而来的,它比面向过程编程具有更强的灵活性和扩展性。面向对象程序设计也是一个程序员发展的 “分水岭”,很多的初学者…...
基于DelayQueue实现的延时队列
基于java中延时队列的实现该文章,我们这次主要是来实现基于DelayQueue实现的延时队列。 使用DelayQueue实现的延时队列的步骤: 定义一个继承了Delayed的类,定义其中的属性,并重写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 包中的官方声明 随着应用的增长,静态类型系统可以帮助防止许多潜在的运行时错误,这就是为什么 Vue 3 是用 TypeScript 编写的。这意味着在 Vue 中使用 TypeScript 不需要任何其他工具——它具有一流的公…...
STM8S系列基于IAR标准外设printf输出demo
STM8S系列基于IAR标准外设printf输出demo📌STM8S/A标准外设库(库版本V2.3.1)📍官网标准外设库:https://www.st.com/zh/embedded-software/stsw-stm8069.html ⛳注意事项 🚩在内存空间比较有限的情况下&am…...
PMP项目管理项目质量管理
目录1 项目质量管理概述2 规划质量管理3 管理质量4 控制质量1 项目质量管理概述 项目质量管理包括把组织的质量政策应用于规则、管理、控制项目和产品质量要求,以满足相关方目标的各个过程。项目质量管理还将以组织的名义支持过程的持续改进活动。 核心概念 质量是…...
前缀和总结
前缀和是一个常用的算法技巧,通常用于求解数组或序列的区间和。 具体来说,假设有一个长度为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 概念 二分图是一种能将所有结点分为两部分的图,其中图的每条边所连接的两个顶点都分别属于不同的部分。 2 API public classBipartiteBipartite(Graph G)预处理函数public booleanisBipartitle()是否是二分图pub…...
计算机网络题库---选择题刷题训练(100多道精品)
第一章 概述 1.下列四项内容中,不属于Internet(因特网)基本功能是___D_____。 A.电子邮件 B.文件传输 C.远程登录 D.实时监测控制 2.Internet是建立在____C_____协议集上的国际互联网络。 A.IPX B.NetBEUI C.TCP/IP …...
16、字符串生成器
目录 (1)append()方法 (2)insert(int offset, arg)方法 (3)delete(int start , int end)方法 创建成功的字符串对象,其长度是固定的,内容不能被改变和编译。虽然使用“”可以达到…...
苹果内购Java后端避坑指南:沙盒测试、凭据验证与订单防重的那些事儿
苹果内购Java后端避坑指南:沙盒测试、凭据验证与订单防重的那些事儿 第一次对接苹果应用内购(IAP)时,我以为按照官方文档走完流程就万事大吉了。直到凌晨三点收到服务器告警——重复充值、验证超时、沙盒环境漏测等问题接踵而至。…...
国际大牌入门之选
这些品牌是轻奢饰品界的常青树,设计经典,辨识度高,是很多人的入门首选。卡地亚 27%人推荐猎豹为图腾,工艺精湛,是轻奢界的经典与传奇。宝格丽 24%人推荐跃马徽记是其标志,珠宝设计性感矜贵,灵蛇…...
如何快速配置HomeAssistant格力空调本地控制组件:完整操作指南
如何快速配置HomeAssistant格力空调本地控制组件:完整操作指南 【免费下载链接】HomeAssistant-GreeClimateComponent Custom Gree climate component written in Python3 for Home Assistant. Controls ACs supporting the Gree protocol. 项目地址: https://git…...
华为新机散热“封神”:拆解仿生羽翼涡扇,看“小翅膀”如何颠覆手机温控
🎓作者简介:科技自媒体优质创作者 🌐个人主页:莱歌数字-CSDN博客 💌公众号:莱歌数字(B站同名) 📱个人微信:yanshanYH 211、985硕士,从业16年 从…...
Yep应用商店优化终极指南:提升App Store排名与下载量的10个策略
Yep应用商店优化终极指南:提升App Store排名与下载量的10个策略 【免费下载链接】Yep Meet Genius 项目地址: https://gitcode.com/gh_mirrors/ye/Yep Yep是一款主打社交互动的移动应用,通过优化App Store展示内容和用户体验,可以显著…...
OpenClaw隐私保护方案:ollama-QwQ-32B本地化数据处理流程
OpenClaw隐私保护方案:ollama-QwQ-32B本地化数据处理流程 1. 为什么需要本地化隐私保护方案 去年我在处理一份涉及客户隐私的市场分析报告时,遇到了一个棘手问题:当使用云端AI服务进行数据清洗和分析时,不得不将包含敏感字段的原…...
Word制表位全攻略:从菜鸟到高手,5分钟搞定专业文档排版
Word制表位全攻略:从菜鸟到高手,5分钟搞定专业文档排版 你是否曾经为了对齐文档中的文字而疯狂敲击空格键?或是花费大量时间调整表格边框却依然无法让数字完美对齐?这些困扰其实只需要掌握一个Word中的隐藏神器——制表位&#x…...
SLANeXt_wireless_safetensors:免费AI无线安全工具入门指南
SLANeXt_wireless_safetensors:免费AI无线安全工具入门指南 【免费下载链接】SLANeXt_wireless_safetensors 项目地址: https://ai.gitcode.com/paddlepaddle/SLANeXt_wireless_safetensors 导语:SLANeXt_wireless_safetensors作为一款免费的AI无…...
机器视觉中的坐标系转换:从像素到世界的无缝衔接
1. 机器视觉中的坐标系基础概念 第一次接触机器视觉时,最让我困惑的就是各种坐标系之间的关系。记得当时调试工业相机时,明明在图像上看到了目标物体,但机械臂就是抓不准位置。后来才发现,问题出在没有正确理解像素坐标系和世界坐…...
利用快马平台快速生成proteus仿真项目,十分钟搭建arduino温湿度监测原型
作为一名电子爱好者,最近在做一个温湿度监测的小项目。传统方式需要先在电脑上安装Proteus、Arduino IDE等一堆软件,配置起来特别麻烦。后来发现了InsCode(快马)平台,简直打开了新世界的大门——不用安装任何软件,直接在网页上就能…...
