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

SpringSecurity高级用法

SpringSecurity的高级用法,包括自定义loginUrl携带参数,自定义认证校验逻辑,自定义权限校验逻辑。 示例项目 https://github.com/qihaiyan/springcamp/tree/master/spring-advanced-security

一、概述

在项目实际开发过程中,SpringSecurity默认的认证和权限校验逻辑不能实现很高的业务复杂度,这种情况下我们需要自定义这些逻辑,包括自定义loginUrl携带参数,自定义认证校验逻辑,自定义权限校验逻辑。

二、自定义loginUrl携带参数

SpringSecurity在跳转login页面时,虽然可以指定login的url,但是无法让url中携带动态参数,不如跳转到login?param=foo,其中foo需要根据特定条件动态变化,要实现这种效果,我们需要通过exceptionHandling指定自定义LoginUrlAuthenticationEntryPoint。

public class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();public CustomLoginUrlAuthenticationEntryPoint(String loginFormUrl) {super(loginFormUrl);}@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)throws IOException, ServletException {if (!super.isUseForward()) {String redirectUrl = this.buildRedirectUrlToLoginPage(request, response, authException);// change login urlredirectUrl = redirectUrl + "?param=test";this.redirectStrategy.sendRedirect(request, response, redirectUrl);} else {String redirectUrl = null;if (super.isForceHttps() && "http".equals(request.getScheme())) {redirectUrl = this.buildHttpsRedirectUrlForRequest(request);}if (redirectUrl != null) {this.redirectStrategy.sendRedirect(request, response, redirectUrl);} else {String loginForm = this.determineUrlToUseForThisRequest(request, response, authException);RequestDispatcher dispatcher = request.getRequestDispatcher(loginForm);dispatcher.forward(request, response);}}}
}

以上代码自定义CustomLoginUrlAuthenticationEntryPoint,在commence方法中我们可以按照业务需要实现自己的跳转逻辑,通过修改redirectUrl实现。

在SpringSecurity配置中通过exceptionHandling引用CustomLoginUrlAuthenticationEntryPoint:

exceptionHandling(customizer ->customizer.authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint("/login")))

三、自定义认证校验逻辑

SpringSecurity默认的认证逻辑是校验用户名密码是否合法,如果想增加其它的校验逻辑,需要实现AuthenticationProvider,然后在authenticationManager中指定我们自己实现的AuthenticationProvider。

public class CustomAuthenticationProvider extends DaoAuthenticationProvider {@Autowiredprivate CustomUserDetailsService customUserDetailsService;@PostConstructpublic void init() {this.setUserDetailsService(customUserDetailsService);}@Overrideprotected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) {super.additionalAuthenticationChecks(userDetails, authentication);HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();String username = userDetails.getUsername();// 自定义认证校验逻辑if (username.equals("need approval")) {log.info("invalid request is: {}", req);throw new AuthenticationServiceException("Your account is pending approval for access");}}
}

在上面自定义的CustomAuthenticationProvider中,通过重写additionalAuthenticationChecks方法进行自定义认证逻辑的实现。

然后在authenticationManager中指定CustomAuthenticationProvider:

@Bean
public AuthenticationManager authenticationManager() {return new ProviderManager(customAuthenticationProvider);
}

四、自定义权限校验逻辑

SpringSecurity可以通过在配置中通过requestMatchers指定较为灵活的权限校验策略,但是缺少一些动态特性,比如对 /foo/{param} 这种rest风格的带变量的url就处理不了,
这种情况我们可以通过自定义AuthorizationManager来实现,然后在requestMatchers中通过access方法来指定我们自定义的AuthorizationManager。

public class MyRequestAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {private final SecurityExpressionHandler<RequestAuthorizationContext> expressionHandler = new DefaultHttpSecurityExpressionHandler();public MyRequestAuthorizationManager() {}// 自定义授权校验逻辑@Overridepublic AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {EvaluationContext ctx = this.expressionHandler.createEvaluationContext(authentication, context);String checkParam = Optional.ofNullable(ctx.lookupVariable("param")).map(String::valueOf).orElse(null);// the '/public' url doesn't need authenticationif (checkParam != null && (checkParam.equals("public"))) {return new AuthorizationDecision(true);}return new AuthorizationDecision(!ObjectUtils.isEmpty(authentication.get().getCredentials()));}
}

在MyRequestAuthorizationManager中通过重写check方法来实现自定义权限校验,rest风格的带变量的url中的变量,可以通过EvaluationContext的lookupVariable方法获取变量值。

指定自定义AuthorizationManager:

MyRequestAuthorizationManager myRequestAuthorizationManager = new MyRequestAuthorizationManager();
http.authorizeHttpRequests(authorize -> authorize.requestMatchers("/{param}").access(myRequestAuthorizationManager))

相关文章:

SpringSecurity高级用法

SpringSecurity的高级用法&#xff0c;包括自定义loginUrl携带参数&#xff0c;自定义认证校验逻辑&#xff0c;自定义权限校验逻辑。 示例项目 https://github.com/qihaiyan/springcamp/tree/master/spring-advanced-security 一、概述 在项目实际开发过程中&#xff0c;Spr…...

qwen2.5-vl-7B视觉大模型 私有化部署webUI

服务器选用&#xff1a;算力云 部署qwen2.5-vl-7B&#xff0c;24g显卡跑不起图&#xff0c;单问问题就占20g左右。有能力可以用大点的显卡 一、下载模型 Qwen2.5-VL-7B-Instruct 有conda &#xff0c;可以在conda下操作&#xff0c;不知道conda的同学可以参考本博主之前的文章…...

java安全中的类加载

java安全中的类加载 提前声明: 本文所涉及的内容仅供参考与教育目的&#xff0c;旨在普及网络安全相关知识。其内容不代表任何机构、组织或个人的权威建议&#xff0c;亦不构成具体的操作指南或法律依据。作者及发布平台对因使用本文信息直接或间接引发的任何风险、损失或法律纠…...

如何在Windows中配置MySQL?

MySQL是一个广泛使用的开源关系型数据库管理系统&#xff0c;它支持多种操作系统平台&#xff0c;其中包括Windows。无论是开发者进行本地开发&#xff0c;还是管理员为应用程序配置数据库&#xff0c;MySQL都是一个非常流行的选择。本篇文章将详细介绍如何在Windows操作系统中…...

Docker Desktop 镜像源配置

1 打开配置页面 2 docker engine 镜像配置位置 3、替换镜像内容 {"registry-mirrors": ["https://hub-mirror.c.163.com","https://mirror.ccs.tencentyun.com","https://05f073ad3c0010ea0f4bc00b7105ec20.mirror.swr.myhuaweicloud.c…...

125,【1】攻防世界unserialize3

进入靶场 代码 <?php // 定义一个名为 xctf 的类 class xctf {// 定义一个公共属性 $flag&#xff0c;初始值为字符串 111public $flag 111;// 定义 __wakeup() 魔术方法// 当使用 unserialize() 函数反序列化对象时&#xff0c;会自动调用 __wakeup() 方法// 在这个方法…...

2025年数据资产管理解决方案:资料合集,从基础知识到行业应用的全面解析

在数字化时代&#xff0c;数据已成为企业最宝贵的资产之一。如何有效地管理和利用这些数据&#xff0c;将其转化为实际的经济价值&#xff0c;已成为企业面临的重要课题。 本文将通过数据资产解决方案、数据资产行业报告白皮书、数据资产政策汇编、数据资产基础知识以及数据资…...

Python与R机器学习(1)支持向量机

以下是对Python与R在支持向量机&#xff08;SVM&#xff09;实现上的核心区别分析及完整示例代码&#xff1a; 一、核心差异对比 特征Python (scikit-learn)R (e1071/kernlab)核心库sklearn.svm.SVC/SVRe1071::svm() 或 kernlab::ksvm()语法范式面向对象&#xff08;先初始化模…...

Render上后端部署Springboot + 前端Vue 问题及解决方案汇总

有一个 Vue 前端 和 Spring Boot 后端的动态网页游戏&#xff0c;当前在本地的 5173 端口和运行。你希望生成一个公开链接&#xff0c;让所有点击链接的人都能访问并玩这个游戏。由于游戏原本需要在本地执行 npm install 后才能启动&#xff0c;你现在想知道在部署时是选择 Ren…...

朝天椒USB服务器:解决加密狗远程连接

本文探讨朝天椒USB服务器用Usb Over Network技术&#xff0c;解决加密狗在虚拟机、云主机甚至异地的远程连接问题。 在企业数字化转型的浪潮中&#xff0c;加密狗作为防止软件盗版的重要手段&#xff0c;广泛应用于各类软件授权场景。然而&#xff0c;随着企业超融合进程不断加…...

Unity Shader Feature

Shader Feature 设置Keyword //0:Red 1:Green 2:Blue Mat.SetInt(“_Color”,0); 需要在创建时进行设置&#xff0c;运行时不可设置 Shader "Unlit/KeywordEnum" {Properties{[KeywordEnum(Red,Green,Blue)] _Color("Color",int) 0}SubShader{Pass{HLSL…...

前端开发环境

vscde nrm 切换源管理 nvm 切换node版本工具 nodemon node运行js文件热更新 pxcook 易用的自动标注工具, 生成前端代码, 设计研发协作利器,比PS轻量 TypeScript 安装tsc 它的作用就是将ts文件编译为js文件 npm i typescript -g 输入tsc -v能够看到东西&#xff0c;就说明好了 …...

c语言判断一个文件的文件格式

在 Linux 下使用 C 语言判断一个文件的文件格式&#xff0c;通常需要检查文件的头信息&#xff08;也称为“幻数”或“魔数”&#xff09;。不同的文件格式在文件头有特定的字节序列&#xff0c;这些字节序列可以用来确定文件的类型。以下是一个基本的示例&#xff0c;展示了如…...

厘米和磅的转换关系

在排版和设计领域&#xff0c;厘米&#xff08;cm&#xff09;和磅&#xff08;pt&#xff09;都是常用的长度度量单位&#xff0c;它们之间的转换关系基于特定的换算标准&#xff0c;下面为你详细介绍&#xff1a; 基本换算关系 磅是印刷行业常用的长度单位&#xff0c;1英寸…...

汽车与AI深度融合:CES Asia 2025前瞻

在科技飞速发展的当下&#xff0c;汽车与AI的融合正成为行业变革的关键驱动力。近日&#xff0c;吉利、极氪、岚图、智己等多家车企纷纷官宣与DeepSeek模型深度融合&#xff0c;其中岚图知音更是将成为首个搭载该模型的量产车型&#xff0c;这无疑是汽车智能化进程中的重要里程…...

用easyExcel如何实现?

要使提供的 ExcelModelListener 类来解析 Excel 文件并实现批量存储数据库的功能&#xff0c;需要结合 EasyExcel 库来读取 Excel 数据。具体来说&#xff0c;可以使用 EasyExcel.read() 方法来读取 Excel 文件&#xff0c;并指定 ExcelModelListener 作为事件监听器。 下面是…...

停止回答 TypeError: (0 , _vue.defineComponent) is not a function

在 Vue.js 中遇到 TypeError: (0 , _vue.defineComponent) is not a function 错误通常意味着 defineComponent 函数没有被正确导入或者你的 Vue 版本不支持该函数。 解决步骤 检查 Vue 版本 defineComponent 是 Vue 3 中的一个功能&#xff0c;用于创建组件。确保你正在使用…...

数据结构与算法-单链表

链表 参考学习&#xff1a;B站-逊哥带你学编程 单链表 单链表-存储结构 typedef int ElemType;typedef struct node{ElemType data;struct node *next; }Node;单链表-初始化 Node *initList() {Node *head (Node *)malloc(sizeof(Node));head->data 0;head->next …...

ASP.NET Core 如何使用 C# 向端点发出 POST 请求

使用 C#&#xff0c;将 JSON POST 到 REST API 端点&#xff1b;如何从 REST API 接收 JSON 数据。 本文需要 ASP .NET Core&#xff0c;并兼容 .NET Core 3.1、.NET 6和.NET 8。 要从端点获取数据&#xff0c;请参阅本文。 使用 . 将 JSON 数据发布到端点非常容易HttpClien…...

DeepSeek模型R1服务器繁忙,怎么解决?

在当今科技飞速发展的时代&#xff0c;人工智能领域不断涌现出令人瞩目的创新成果&#xff0c;其中DeepSeek模型无疑成为了众多关注焦点。它凭借着先进的技术和卓越的性能&#xff0c;在行业内掀起了一股热潮&#xff0c;吸引了无数目光。然而&#xff0c;如同许多前沿技术在发…...

GlusterFS 深度洞察:从架构原理到案例实践的全面解读(上)

文章目录 一.GlusterFS简介二.GlusterFS原理架构三.适用场景四.Glusterfs与其他存储产品对比五.部署GlusterFS集群六. 使用heketi将glusterfs接入k8s作为后端存储 一.GlusterFS简介 GlusterFS是一个免费的开源分布式文件系统&#xff0c;具有无中心节点、堆栈式设计、全局统一…...

更新无忧:用 Docker 数据卷确保 Open WebUI 数据持久化

在使用 Docker 部署 Open WebUI 时&#xff0c;如何在更新容器的同时确保数据不丢失&#xff0c;始终是工程师们关注的焦点。每次拉取新版镜像、停止并重启容器时&#xff0c;如果没有正确挂载数据卷&#xff0c;配置和数据库数据极易流失&#xff0c;给生产环境带来不必要的麻…...

zyNo.22

常见Web漏洞解析 命令执行漏洞 1.Bash与CMD常用命令 &#xff08;1&#xff09;Bash 读取文件&#xff1a;最常见的命令cat flag 在 Bash 中&#xff0c;cat 以及的tac、nl、more、head、less、tail、od、pr 均为文件读取相关命令&#xff0c;它们的区别如下&#xff1a; …...

idea如何使用AI编程提升效率-在IntelliJ IDEA 中安装 GitHub Copilot 插件的步骤-卓伊凡

idea如何使用AI编程提升效率-在IntelliJ IDEA 中安装 GitHub Copilot 插件的步骤-卓伊凡 问题 idea编译器 安装copilot AI工具 实际操作 在 IntelliJ IDEA 中安装 GitHub Copilot 插件的步骤如下&#xff1a; 打开 IntelliJ IDEA&#xff1a; 打开你的 IntelliJ IDEA 应用…...

有哪些PHP开源框架属于是“高开疯走”的?

“高开疯走”是一个网络流行语或者谐音梗。可能是指一开始起点很高&#xff08;高开&#xff09;&#xff0c;然后发展迅速或者变得非常牛&#xff08;疯走&#xff09;。 在PHP生态中&#xff0c;一些框架面对市场的风起云涌&#xff0c;能持续保持高质量发展&#xff0c;切实…...

C# ASP.NET核心特性介绍

.NET学习资料 .NET学习资料 .NET学习资料 在当今的软件开发领域中&#xff0c;C# ASP.NET凭借其强大的功能和丰富的特性&#xff0c;成为构建 Web 应用程序的重要技术之一。以下将详细介绍 C# ASP.NET的核心特性。 多语言支持 ASP.NET 支持多种语言进行开发&#xff0c;这使…...

在 Linux 系统下,解压 `.tar.gz`

在 Linux 系统下,解压 .tar.gz 文件通常使用 tar 命令。.tar.gz 文件是一种压缩归档文件,它首先使用 tar 命令将多个文件打包为一个 .tar 文件,然后再使用 gzip 压缩生成 .tar.gz 文件。 解压 .tar.gz 文件的命令 要解压 .tar.gz 文件,可以使用以下命令: tar -xzvf fil…...

Unity 接入Tripo 文生模型,图生模型

官方网站&#xff1a;https://www.tripo3d.ai/app/home自行注册账号并且登陆下载Unity插件&#xff1a;https://cdn-web.tripo3d.ai/plugin/tripo-unity.zip申请apikey&#xff1a; https://platform.tripo3d.ai/api-keys使用&#xff08;后续过程就按照第二步下载的插件里面的…...

WPS计算机二级•文档的文本样式与编号

听说这是目录哦 标题级别❤️新建文本样式 快速套用格式&#x1fa77;设置标题样式 自定义设置多级编号&#x1f9e1;使用自动编号&#x1f49b;取消自动编号&#x1f49a;设置 页面边框&#x1f499;添加水印&#x1fa75;排版技巧怎么分栏&#x1f49c;添加空白下划线&#x…...

安卓使用JExcelApi读取Excel文件

要在安卓应用中使用JExcelApi读取Excel文件&#xff0c;你需要先确保你的项目中已经添加了JExcelApi的依赖。由于安卓项目的构建方式多样&#xff0c;这里以使用Gradle为例来介绍如何在安卓应用中集成和使用JExcelAPI。 ### 步骤1: 添加依赖 首先&#xff0c;在你的build.gra…...