Spring Security 多过滤链的使用

news2024/11/19 17:36:02

一、背景

在我们实际的开发过程中,有些时候可能存在这么一些情况,某些api 比如: /api/** 这些是给App端使用的,数据的返回都是以JSON的格式返回,且这些API的认证方式都是使用的TOKEN进行认证。而除了 /api/** 这些API之外,都是给网页端使用的,需要使用表单认证,给前端返回的 都是某个页面。

二、需求

1、给客户端使用的api

1.拦截 /api/**所有的请求。2./api/**的所有请求都需要ROLE_ADMIN的角色。3.从请求头中获取 token,只要获取到token的值,就认为认证成功,并赋予ROLE_ADMIN到角色。4.如果没有权限,则给前端返回JSON对象 {message:"您无权限访问"}5.访问 /api/userInfo端点1.请求头携带 token 可以访问。2.请求头不携带token不可以访问。

2、给网站使用的api

1.拦截 所有的请求,但是不处理/api/**开头的请求。
2.所有的请求需要ROLE_ADMIN的权限。
3.没有权限,需要使用表单登录。
4.登录成功后,访问了无权限的请求,直接跳转到百度去。
5.构建2个内建的用户1.用户一: admin/admin 拥有 ROLE_ADMIN 角色2.用户二:dev/dev 拥有 ROLE_DEV 角色
6.访问 /index 端点1.admin 用户访问,可以访问。2.dev 用户访问,不可以访问,权限不够。

三、实现方案

方案一:

直接拆成多个服务,其中 /api/** 的成为一个服务。非/api/**的拆成另外一个服务。各个服务使用自己的配置,互不影响。

方案二

在同一个服务中编写。不同的请求使用不同的SecurityFilterChain来实现。

经过考虑,此处采用方案二来实现,因为方案一简单,使用方案二实现,也可以记录下在同一个项目中 通过使用多条过滤器链,因为并不是所有的时候,都是可以分成多个项目的。

扩展:

1、Spring Security SecurityFilterChain 的结构

2、控制 SecurityFilterChain 的执行顺序

使用 org.springframework.core.annotation.Order 注解。

3、查看是怎样选择那个 SecurityFilterChain

查看 org.springframework.web.filter.DelegatingFilterProxy#doFilter方法

四、实现

1、app 端 Spring Security 的配置

package com.huan.study.security.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;

/**
 * 给 app 端用的 Security 配置
 *
 * @author huan.fu 2021/7/13 - 下午9:06
 */
@Configuration
public class AppSecurityConfig {/** * 处理 给 app(前后端分离) 端使用的过滤链 * 以 json 的数据格式返回给前端 */@Bean@Order(1)public SecurityFilterChain appSecurityFilterChain(HttpSecurity http) throws Exception {// 只处理 /api 开头的请求return http.antMatcher("/api/**").authorizeRequests()// 所有以 /api 开头的请求都需要 ADMIN 的权限.antMatchers("/api/**").hasRole("ADMIN").and()// 捕获到异常,直接给前端返回 json 串.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {response.setStatus(HttpStatus.UNAUTHORIZED.value());response.setCharacterEncoding(StandardCharsets.UTF_8.name());response.setContentType(MediaType.APPLICATION_JSON.toString());response.getWriter().write("{\"message:\":\"您无权访问01\"}");}).accessDeniedHandler((request, response, accessDeniedException) -> {response.setStatus(HttpStatus.UNAUTHORIZED.value());response.setCharacterEncoding(StandardCharsets.UTF_8.name());response.setContentType(MediaType.APPLICATION_JSON.toString());response.getWriter().write("{\"message:\":\"您无权访问02\"}");}).and()// 用户认证.addFilterBefore((request, response, chain) -> {// 此处可以模拟从 token 中解析出用户名、权限等String token = ((HttpServletRequest) request).getHeader("token");if (!StringUtils.hasText(token)) {chain.doFilter(request, response);return;}Authentication authentication = new TestingAuthenticationToken(token, null,AuthorityUtils.createAuthorityList("ROLE_ADMIN"));SecurityContextHolder.getContext().setAuthentication(authentication);chain.doFilter(request, response);}, UsernamePasswordAuthenticationFilter.class).build();}
} 

2、网站端 Spring Secuirty 的配置

package com.huan.study.security.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

/**
 * 给 网站 应用的安全配置
 *
 * @author huan.fu 2021/7/14 - 上午9:09
 */
@Configuration
public class WebSiteSecurityFilterChainConfig {/** * 处理 给 webSite(非前后端分离) 端使用的过滤链 * 以 页面 的格式返回给前端 */@Bean@Order(2)public SecurityFilterChain webSiteSecurityFilterChain(HttpSecurity http) throws Exception {AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);// 创建用户authenticationManagerBuilder.inMemoryAuthentication().withUser("admin").password(new BCryptPasswordEncoder().encode("admin")).authorities(AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN")).and().withUser("dev").password(new BCryptPasswordEncoder().encode("dev")).authorities(AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_DEV")).and().passwordEncoder(new BCryptPasswordEncoder());// 只处理 所有 开头的请求return http.antMatcher("/**").authorizeRequests()// 所有请求都必须要认证才可以访问.anyRequest().hasRole("ADMIN").and()// 禁用csrf.csrf().disable()// 启用表单登录.formLogin().permitAll().and()// 捕获成功认证后无权限访问异常,直接跳转到 百度.exceptionHandling().accessDeniedHandler((request, response, exception) -> {response.sendRedirect("http://www.baidu.com");}).and().build();}/** * 忽略静态资源 */@Beanpublic WebSecurityCustomizer webSecurityCustomizer( ){return web -> web.ignoring().antMatchers("/**/js/**").antMatchers("/**/css/**");}
} 

3、控制器写法

/**
 * 资源控制器
 *
 * @author huan.fu 2021/7/13 - 下午9:33
 */
@Controller
public class ResourceController {/** * 返回用户信息 */@GetMapping("/api/userInfo")@ResponseBodypublic Authentication showUserInfoApi() {return SecurityContextHolder.getContext().getAuthentication();}@GetMapping("/index")public String index(Model model){model.addAttribute("username","张三");return "index";}
} 

4、引入jar包

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> 

五、实现效果

1、app 有权限访问 api

2、app 无权限访问 api

3、admin 用户有权限访问 网站 api

4、dev 用户无权限访问 网站 api

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/163293.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt扫盲-QTextEdit理论总结

QTextEdit理论总结一、概述二、用途一&#xff1a;富文本阅读器1. 用法2. 快捷键绑定三、用途二&#xff1a;编辑器1. 用法2. 拖拽3. 快捷键绑定四、常用功能五、信号一、概述 QTextEdit是一个先进的所见即所得的 富文本 查看器/编辑器&#xff0c;支持使用 html 风格的标签或…

【QT】.pro 文件

&#x1f33f;作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;QT开发 .pro 文件是什么 .pro就是工程文件(project)&#xff0c;它是qmake自动生成的用于生产makefile的配置文件。类似于VS中的.sln 和vsproj文件 默认情况下&#xff0c;每个 Qt 项目都包含一个后缀名为…

Huffman编码实现文件的压缩和解压缩

一个项目&#xff0c;不过处理起来也比较麻烦&#xff0c;配套可以和文件传输放一起 前提知识&#xff1a; 哈夫曼树和哈夫曼编码的概念和构建 1&#xff1a;n个数构成的哈夫曼树一共有2*n-1个结点>8 -> 15 2&#xff1a;数字越大的数离根节点越近&#xff0c;越小的数离…

无线耳机跑步会不会掉、最适合跑步用的耳机排名

现在&#xff0c;喜欢运动的人越来越多了。大家都有体会&#xff0c;多数运动是相对枯燥的&#xff0c;在运动时听听音乐&#xff0c;那是多么惬意的事情啊。为此&#xff0c;体验过多款耳机&#xff0c;但令我很满意的甚少。相信不少喜欢运动的朋友都有着跟我一样的烦恼吧&…

【Java基础知识3】Java注释:单行、多行、文档注释(如何通过 javadoc 命令生成代码文档、如何在IEDA配置自动为所有的类都添加创建者和创建日期)

本文已收录专栏 &#x1f332;《Java进阶之路》&#x1f332; 目录 本文已收录专栏 &#x1f332;《Java进阶之路》&#x1f332; &#x1f350;01、单行注释 &#x1f350;02、多行注释 &#x1f350;03、文档注释 &#x1f350;04、文档注释的注意事项 &#x1f350;05、注释…

ceres学习笔记(二)

继续关于ceres官方doc里教程的学习&#xff0c;对于powells function的学习。 一、powells function 鲍威尔法&#xff0c;严格来说是鲍威尔共轭方向法&#xff0c;是迈克尔J.D.鲍威尔提出的一种求解函数局部最小值的算法。该函数不能是可微分的&#xff0c;并且不会导出衍生函…

spring用注解读取与获取对象

前言 上一篇博客简单的介绍了spring的功能与使用&#xff0c;可以看到我们创建一个对象&#xff0c;就需要在xml中存储一个bean对象&#xff0c;这种操作非常的繁琐&#xff0c;因此spring发明了使用注解来快捷存储bean对象 配置工作 我们在xml文件中写下面的代码片段 <…

基于风光储能和需求响应的微电网日前经济调度(Python代码实现)【0】

目录 0 引言 1 计及风光储能和需求响应的微电网日前经济调度模型 1.1风光储能需求响应都不参与的模型 1.2风光参与的模型 1.3风光和储能参与模型 1.4 风光和需求响应参与模型 1.5 风光储能和需求响应都参与模型 2 需求侧响应评价 2.1 负载率 2.2 可再生能源消纳率 …

Win10PE_V2.0Nvme网络版.iso 支持Nvme硬盘免费下载无需积分

Win10PE_V2.0Nvme网络版.iso 支持Nvme硬盘免费下载无需积分 V1.0版本发布 2022年1月19日 内置常用PE工具&#xff0c;7-Zip、EasyImageX_x64、XorBoot Uefi修复、NT6修复、Ghost、CGI、Google浏览器、PENetwork、RegWorkshop、迅雷迷你版、、BOOTICEx64、windows安装器、XP安…

路径计数2

路径计数2 题目描述 一个NNN \times NNN的网格&#xff0c;你一开始在(1,1)(1,1)(1,1)&#xff0c;即左上角。每次只能移动到下方相邻的格子或者右方相邻的格子&#xff0c;问到达(N,N)(N,N)(N,N)&#xff0c;即右下角有多少种方法。 但是这个问题太简单了&#xff0c;所以现…

MySQL 数据同步 Elasticsearch 的技术方案选型

文章目录1.同步双写2.异步双写3.定时任务4.数据订阅1.同步双写 优点&#xff1a;实现简单缺点&#xff1a; 业务耦合&#xff0c;商品的管理中耦合大量数据同步代码 影响性能&#xff0c;写入两个存储&#xff0c;响应时间变长 不便扩展&#xff1a;搜索可能有一些个性化需求&…

jvm学习的核心(三)---运行时数据区详解(1)

图片等相关信息来源于&#xff1a;尚硅谷宋红康JVM全套教程 1.程序计数器 程序计数器又叫pc寄存器&#xff0c;中文有两个名字 我们可以反编译字节码文件查看方法中操作指令对应的指令地址 javap -v "对应的class文件"为什么要用pc寄存器&#xff0c;pc寄存器有什…

13、Javaweb_Filter登陆验证动态代理过滤敏感词Listener

Filter&#xff1a;过滤器 1. 概念&#xff1a; * 生活中的过滤器&#xff1a;净水器,空气净化器&#xff0c;土匪、 * web中的过滤器&#xff1a;当访问服务器的资源时&#xff0c;过滤器可以将请求拦截下来&#xff0c;完成一些特殊的功能。 * 过滤器的作用&…

深入理解计算机系统_可执行目标文件和可重定位目标文件的3个区别

这篇笔记对比一下可执行目标文件和可执行目标的3个区别。下图分别是可重定位目标文件和可执行目标文件各段结构。 1.1 可执行目标文件和可重定位目标文件的3个区别 区别1&#xff1a;可执行目标文件的rel.text和.rel.data消失了 链接器将.o中.text和.data节整合到一起时&a…

【ROS2入门】理解 ROS 2 Topics 话题

大家好&#xff0c;我是虎哥&#xff0c;从今天开始&#xff0c;我将花一段时间&#xff0c;开始将自己从ROS1切换到ROS2&#xff0c;在上一篇中&#xff0c;我们一起了解ROS 2中节点的功能以及与之交互的工具&#xff0c; 这一篇&#xff0c;我们主要会围绕ROS中另外一个重要的…

RS232 RS485 TO ETH TCP-Modbus 测试

原来modbus 传感器都是有对应的指令码的&#xff0c;不同功能的指令码也不一样&#xff0c;比如测温度和湿度的指令码也是不一样的&#xff1b; 硬件连接如下图 &#xff08;温湿度传感器&#xff0c;板载SHT20&#xff09; ​ 编辑切换为居中 添加图片注释&#xff0c;不超…

华为VRRP、BFD实验配置

目录 VRRP实验配置 BFD实验配置 配置单跳检测 配置多跳检测 配置单臂回声 BFD与路由协议联动配置 BFD与OSPF联动 BFD与ISIS联动 BFD与BGP联动 VRRP实验配置 VRRP配置 AR1配置&#xff08;VRRP缺省优先级100&#xff09; int g0/0/0 ip add 192.168.10.1 24 vrrp vrid …

织音云站长扶持计划:可免费获得CDN或虚拟主机

活动介绍活动详情页&#xff1a;织音云站长扶持计划网站被恶意攻击时是中小站长最脆弱的时候&#xff0c;90%的站长都会动“关站不干了”的心思&#xff0c;夹在中间真的很难搞!因此织音云决定为中小站长提供免费的全球CDN加速服务和提供免费的虚拟主机,免备案&#xff01;只需…

智改数转水循环在线监测系统,提升企业生产安

江苏省政府印发《江苏省制造业智能化改造和数字化转型三年行动计划&#xff08;2022&#xff0d;2024年&#xff09;》&#xff0c;提出通过三年的努力&#xff0c;全省制造业数字化、网络化、智能化水平显著提升&#xff0c;新业态、新模式、新动能显著壮大&#xff0c;制造业…

linux系统中使用QT操作硬件蜂鸣器的方法

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何使用QT进行蜂鸣器的控制与实现。 目录 第一&#xff1a;资源基本简介 第二&#xff1a;应用实例的代码实现 第三&#xff1a;源文件“mainwindow.cpp”的具体实现 第四&#xff1a;程序运行效果 第一&#xff1a;资…