Spring Security- 基于角色的访问控制

news2025/2/25 8:25:41

基于角色 或权限 进行访问控制

hasAuthority方法

如果当前的主体具有指定的权限,则返回true,否则返回false

修改配置类
  //当前登录用户 只有具备admins权限才可以访问这个路径
 .antMatchers("/test/index").hasAuthority("admins")

代码如下:

 package com.config;
 ​
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 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.WebSecurityConfigurerAdapter;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 ​
 @Configuration    //配置类
 public class SecurityConfig extends WebSecurityConfigurerAdapter {
 ​
     @Autowired
     UserDetailsService userDetailsService;
 ​
 ​
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
     }
     @Bean
     PasswordEncoder passwordEncoder(){
         return new BCryptPasswordEncoder();
     }
 ​
     @Override
     protected void configure(HttpSecurity http) throws Exception {
         http.formLogin().loginPage("/login.html")   // 自定义登录页面
                         .loginProcessingUrl("/user/login")     //登录访问路径
                         .defaultSuccessUrl("/test/index").permitAll()      //登录成功后 跳转路径
                         .and().authorizeRequests()
                         .antMatchers("/","/user/login","/test/add").permitAll() //设置哪些路径可以不认证 直接访问
                          //当前登录用户 只有具备admins权限才可以访问这个路径
                         .antMatchers("/test/index").hasAuthority("admins")
                         .and().csrf().disable() ; // 关闭csrf的防护
     }
 }
修改 UserDetailsService, 把 返回的对象 设置权限

代码如下:

 
package com.service;
 ​
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.entity.UserInfo;
 import com.mapper.UserInfoMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.stereotype.Service;
 ​
 import java.util.ArrayList;
 import java.util.List;
 ​
 @Service("userDetailsService")
 public class MyUserDetailsService implements UserDetailsService {
 ​
     @Autowired
     private UserInfoMapper userInfoMapper;
 ​
 ​
 ​
     @Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
 ​
         //根据用户名 查询
         QueryWrapper<UserInfo> wrapper=new QueryWrapper<>();
         wrapper.eq("name",username);   //查询 name列 的值 为 username的 数据
         UserInfo info = userInfoMapper.selectOne(wrapper);
         //判断
         if(info==null){   //没有用户 验证失败
             throw new UsernameNotFoundException("用户名不存在");
         }
 ​
         List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("admins");  //这里与配置类一致
         //返回数据库的用户名及密码
         return new User(info.getName(), new BCryptPasswordEncoder().encode(info.getPwd()),list);
     }
 }

启动测试: 输入正确的用户名及密码, 当前返回的用户 具有admins 权限, 因此可以看到 hello index

接下来 将 上面UserDetailsService的 权限 由 admins改为其他 , 还是输入 正确的用户名及密码则There was an unexpected error (type=Forbidden, status=403).

hasAnyAuthority方法

如果当前的主体由任何提供的角色的话 返回true

修改配置类

具备 admins 或 abc 的 都可以 访问 /test/index

修改UserDetailsService

启动测试:

输入正确的用户名及密码 : 看到 hello index

hasRole

如果用户具备给定角色就允许访问 否则出现403

如果当前主体具有指定的角色则返回true

修改配置类

 package com.config;
 ​
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 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.WebSecurityConfigurerAdapter;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 ​
 @Configuration    //配置类
 public class SecurityConfig extends WebSecurityConfigurerAdapter {
 ​
     @Autowired
     UserDetailsService userDetailsService;
 ​
 ​
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
     }
     @Bean
     PasswordEncoder passwordEncoder(){
         return new BCryptPasswordEncoder();
     }
 ​
     @Override
     protected void configure(HttpSecurity http) throws Exception {
         http.formLogin().loginPage("/login.html")   // 自定义登录页面
                         .loginProcessingUrl("/user/login")     //登录访问路径
                         .defaultSuccessUrl("/test/index").permitAll()      //登录成功后 跳转路径
                         .and().authorizeRequests()
                 //       /user/login","/test/add" 面允许任意访问
                         .antMatchers("/","/user/login","/test/add").permitAll() //设置哪些路径可以不认证 直接访问
                          //当前登录用户 只有具备admins权限才可以访问这个路径
                         //.antMatchers("/test/index").hasAnyAuthority("admins","abc")
                         .antMatchers("/test/index").hasRole("sale")
                         .anyRequest().permitAll()
                         .and().csrf().disable() ; // 关闭csrf的防护
     }
 }
修改UserDetailsService

注意 配置类 写 sale , 这里需要增加前缀 ROLE_

 List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_sale");

启动 访问 输入正确 用户名 /密码 看到 hello index

hasAnyRole

表示用户具备任何一个条件都可以访问

修改配置类
 .antMatchers("/test/index").hasAnyRole("sale","p2")
修改UserDetailsService
 List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_p2");

启动访问 ,输入正确用户名/密码 可以看到 页面 hello index

自定义403页面

在static 下 建立 403.html

 <h1>未授权</h1>

在配置类进行配置:

 //配置没有权限访问跳转的页面
 http.exceptionHandling().accessDeniedPage("/403.html");

完整代码

 package com.config;
 ​
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 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.WebSecurityConfigurerAdapter;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 ​
 @Configuration    //配置类
 public class SecurityConfig extends WebSecurityConfigurerAdapter {
 ​
     @Autowired
     UserDetailsService userDetailsService;
 ​
 ​
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
     }
     @Bean
     PasswordEncoder passwordEncoder(){
         return new BCryptPasswordEncoder();
     }
 ​
     @Override
     protected void configure(HttpSecurity http) throws Exception {
 ​
         //配置没有权限访问跳转的页面
         http.exceptionHandling().accessDeniedPage("/403.html");
 ​
         http.formLogin().loginPage("/login.html")   // 自定义登录页面
                         .loginProcessingUrl("/user/login")     //登录访问路径
                         .defaultSuccessUrl("/test/index").permitAll()      //登录成功后 跳转路径
                         .and().authorizeRequests()
                 //       /user/login","/test/add" 面允许任意访问
                         .antMatchers("/","/user/login","/test/add").permitAll() //设置哪些路径可以不认证 直接访问
                          //当前登录用户 只有具备admins权限才可以访问这个路径
                         //.antMatchers("/test/index").hasAnyAuthority("admins","abc")
                         //.antMatchers("/test/index").hasRole("sale")
                         .antMatchers("/test/index").hasAnyRole("sale","p2")
                         .anyRequest().permitAll()
                         .and().csrf().disable() ; // 关闭csrf的防护
     }
 }

修改 代码 让 其 没有权限 ,输入正确的用户名与密码

4注解方式

@secured

判断是否具有角色,另外需要注意的是这里匹配的字符串需要添加前缀 “ROLE"

使用注解先要开启注解功能!,

@EnableGlobalMethodSecurity(securedEnabled=true)

修改启动类或配置类 开启注解

选择 启动类

 @SpringBootApplication
 @MapperScan(basePackages = "com.mapper")
 @EnableGlobalMethodSecurity(securedEnabled = true)
 public class SSApp {
     public static void main(String[] args) {
         SpringApplication.run(SSApp.class,args);
     }
 }

在controller 方法上 使用注解 ,设置 角色

 
package com.controller;
 ​
 import org.springframework.security.access.annotation.Secured;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 ​
 @RestController
 @RequestMapping("/test")
 public class TestController {
 ​
     @GetMapping("/index")
     public String index(){
         return "hello index";
     }
 ​
 ​
     @GetMapping("/add")
     public String add(){
         return "hello security";
     }
 ​
 ​
 ​
     @GetMapping("/update") 
     @Secured({"ROLE_sale","ROLE_manager"})    ---- 注解访问 ,需要在启动类 开启注解  ,注意前缀
     public String update(){
         return "hello update";
     }
 ​
 ​
 }

在UserDetailsService 中 配置角色

 List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_sale");

启动 测试: 地址栏 输入 localhost:8080/test/update

然后输入 正确的用户名/密码 , 然后看到页面

@PreAuthorize

先开启注解功能

@EnableGlobalMethodSecurity(prePostEnabled = true)

@PreAuthorize:注解适合进入方法前的权限验证

@PreAuthorize可以将登录用户的roles/permissions参数传到方法中。。

使用方式:

在启动类开启注解

 @SpringBootApplication
 @MapperScan(basePackages = "com.mapper")
 @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled=true)
 public class SSApp {
     public static void main(String[] args) {
         SpringApplication.run(SSApp.class,args);
     }
 }

在controller方法上添加注解

 @GetMapping("/update")
 //@Secured({"ROLE_sale","ROLE_manager"})
 @PreAuthorize("hasAnyAuthority('admins','abc')")
 public String update(){
     return "hello update";
 }

在UserDetailsService 中 配置角色或权限

 List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_sale");

启动测试:

@PostAuthorize

先开启注解功能

@EnableGlobalMethodSecurity(prePostEnabled = true)

@PostAuthorize 注解使用并不多, 在方法执行后进行权限验证,适合验证带有返回值的权限

开启注解

 
@SpringBootApplication
 @MapperScan(basePackages = "com.mapper")
 @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled=true)
 public class SSApp {
     public static void main(String[] args) {
         SpringApplication.run(SSApp.class,args);
     }
 }

编写controller , 判断是否 具备 'admins','ROLE_abc'

 @GetMapping("/update")
 //@Secured({"ROLE_sale","ROLE_manager"})
 //@PreAuthorize("hasAnyAuthority('admins','abc')")
 @PostAuthorize("hasAnyAuthority('admins','abc')")
 public String update(){
     System.out.println("update.......");
     return "hello update";
 }

修改UserDetailsService , 让其拥有 admin 与 上面的 admins 不同

 List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_sale");

启动测试 ,输入正确的用户名及密码 , 发现 具备admin 但没有 admins 权限, 控制台会打印 update.... ,然后显示 跳转到未授权页面403.html

@PostFilter 对返回数据做过滤

@PostFilter:权限验证之后对数据进行过滤,留下用户名是admin1的数据.

表达式中的 filterObject 引用的是方法返回值List中的某一个元素-

@PreFilter 对传入参数做过滤

@PreFilter 进入控制器之前对数据进行过滤

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

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

相关文章

【面试合集】说说微信小程序的发布流程?

面试官&#xff1a;说说微信小程序的发布流程&#xff1f; 一、背景 在中大型的公司里&#xff0c;人员的分工非常仔细&#xff0c;一般会有不同岗位角色的员工同时参与同一个小程序项目。为此&#xff0c;小程序平台设计了不同的权限管理使得项目管理者可以更加高效管理整个团…

vue3-模板引用

//1.调用ref函数 -> ref对象 const h1Ref ref(null) const comRef ref(null) //组件挂载完毕之后才能获取 onMounted(()>{console.log(h1Ref.value);console.log(comRef.value); })<div class"father"><!-- 通过ref标识绑定ref对象 --><h2 re…

Apache Zeppelin学习记录2

Apache Zeppelin学习记录2 文章目录 Apache Zeppelin学习记录2前言一、基础调用二、带参数调用1.代码块要增加一行z.textbox("folder_path", "input")2.读取result 总结 前言 上一章讲了如何使用zeppelin来接入python&#xff0c;本节我们来看看如何使用R…

什么情况下物理服务器会运行出错?

​  物理服务器&#xff0c;也称为裸机服务器&#xff0c;一般可以提供高性能计算水平和巨大的存储容量。然而&#xff0c;它们也难免会遇到一些问题。运行出错时&#xff0c;可能会导致停机和数据丢失。在这篇文章中&#xff0c;介绍了常见的物理服务器在一些情况下显示出错…

基于D2-NET的图像配准(基于PYQT的可运行界面)

这是之前对D2-NET的一个封装。D2-NET在图像配准领域还是占有一席之地的。 我们在D2-NET的基础上进行了一些小小的改动&#xff0c;也增加了FLANNRANSAC的提纯策略&#xff0c;同时增加了PYQT的一个界面。 参考的代码&#xff1a;代码1 代码2 首先介绍一下这个界面&#x…

LINUX基础培训九之网络管理

前言、本章学习目标 了解LINUX网络接口和主机名配置的方法熟悉网络相关的几个配置文件了解网关和路由熟悉网络相关的命令使用 一、网络IP地址配置 在Linux中配置IP地址的方法有以下这么几种&#xff1a; 1、图形界面配置IP地址&#xff08;操作方式如Windows系统配置IP&…

机器学习:线性回归模型的原理、应用及优缺点

一、原理 线性回归是一种统计学和机器学习中常用的方法&#xff0c;用于建立变量之间线性关系的模型。其原理基于假设因变量&#xff08;或响应变量&#xff09;与自变量之间存在线性关系。 下面是线性回归模型的基本原理&#xff1a; 模型拟合&#xff1a; 通过最小二乘法&…

2024年“华数杯”国际大学生数学建模竞赛B题思路

本题难点在于数据获取和定性定量分析&#xff0c;代码部分没有太大价值、就不更新了 •中国的电力供应和许多因素相互作用。请研究它们之间的关系&#xff0c;并预测2024年至2060年中国电力供应的发展趋势。 首先得获取数据&#xff0c;中国的宏观数据相对容易&#xff08;包括…

C#/WPF 设置和启动Windows屏保程序

前言 我们平时电脑启动的屏保程序其本质也是应用程序&#xff0c;只是后缀名为.scr。所以我们只需要把应用程序后缀改为.scr&#xff0c;然后右键选择安装即可启动我们自己的屏保程序。 屏保注册表参数 设置电脑屏保参数&#xff0c;在个性化设置>锁屏界面>屏幕保护程序设…

HashTable,HashMap和ConcurrentHashMap

1. 在多线程环境下使用哈希表 1.1 HashMap 对于HashMap来说肯定是不行的&#xff0c;因为HashMap线程是不安全的。 1.2 HashTable HashTable是直接在方法上使用synchronized&#xff0c;就相当于对this加锁。(此时&#xff0c;尝试修改俩个不同链表上的元素&#xff0c;都会发…

c语言:编译和链接

翻译环境和运行环境 在ANSIC的任何⼀种实现中&#xff0c;存在两个不同的环境。 第1种是翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令。 第2种是执行环境&#xff0c;它用于实际执行代码。 编译过程 预处理&#xff08;Preprocessing&#xff09; 文件包…

[Python进阶] 正则表达式的验证

8.2 正则表达式的验证 正则表达式的语法很令人头疼&#xff0c;即使对经常使用它的人来说也是如此。由于难于读写&#xff0c;容易出错&#xff0c;所以找一种工具对正则表达式进行测试是很有必要的。 8.2.1 本地验证 通过Regex Tester这款软件可以在本地对正则表达式进行验…

CTF CRYPTO 密码学-3

题目名称&#xff1a;反编译 题目描述&#xff1a; 分析 题目给出一个pyc后缀的文件&#xff0c;需要使用uncompyle6模块去还原成py文件 uncompyle6简介 uncompyle6 是一个 Python 反编译器&#xff0c;它能够将 Python 字节码&#xff08;.pyc 文件&#xff09;转换回源代码&…

系统的可观察性是指什么?

系统的可观察性是指什么&#xff1f; 本文转自 公众号 ByteByteGo&#xff0c;如有侵权&#xff0c;请联系&#xff0c;立即删除 系统的可观察性是系统设计的重要一环。不可观察的系统无法度量、无法监控、无法改进。 日志、追踪和度量是系统可观测性的三大支柱。 下图显示了…

2019年认证杯SPSSPRO杯数学建模D题(第二阶段)5G时代引发的道路规划革命全过程文档及程序

2019年认证杯SPSSPRO杯数学建模 D题 5G时代引发的道路规划革命 原题再现&#xff1a; 忙着回家或上班的司机们都知道交通堵塞既浪费时间又浪费燃料&#xff0c;甚至有的时候会带来情绪上的巨大影响&#xff0c;引发一系列的交通问题。据报道&#xff0c;每年交通拥堵使得美国…

怎么用Office的Excel将图片转为excel表格?

在处理大量的表格数据时&#xff0c;我们经常需要将图片中的表格转换成Excel格式&#xff0c;以便进行更高效的数据分析和处理。然而&#xff0c;手动将图片中的表格数据录入Excel是一项既耗时又容易出错的工作。那么&#xff0c;有没有一种方法能够快速、准确地实现图片表格到…

从2023年因果推断在线峰会看程序员的未来:掌握因果推理,洞悉数据背后的真相

在科技飞速发展的时代&#xff0c;程序员作为数字世界的建筑师&#xff0c;需要不断拓宽视野&#xff0c;汲取新知识&#xff0c;以应对日益复杂的问题和挑战。 2023年的因果推断在线峰会&#xff0c;为程序员们提供了一个了解因果推理的绝佳机会。本文将探讨程序员在峰会上可…

一种基于YOLO改进的高效且轻量级的表面缺陷检测网络, NEU-DET和GC10-DET涨点明显

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文摘要&#xff1a;一种基于YOLO改进的高效且轻量级的表面缺陷检测&#xff0c; 在NEU-DET和GC10-DET任务中涨点明显 目录 1.轻量且高效的YOLO 1.1 SCRB介绍 1.1.1 ScConv介绍 1.2 GSConvns 1.3 od_mobilenetv2_050 1.4 对应ya…

016-Vue-黑马2023:前后端分离开发(在线接口文档),前端工程化、Element、nginx

第三节 前后端分离开发 1、介绍 开发模式 前后端混合开发&#xff1a;传统开发模式 前后端分离开发&#xff1a;当前最为主流的开发模式 页面原型需求案例&#xff1a;分析出接口文档 离线开发文档示例&#xff1a; 2、YAPI&#xff08;官网已停用&#xff09; 202…

芯品荟 | 电脑机箱键盘副屏市场调研报告

一.产品简介 1.带TFT彩屏电脑机箱 2.带小TFT彩屏电脑键盘 为什么电脑机箱&键盘&#xff0c;要带屏&#xff1f; 带屏的电脑机箱&键盘客户群体? 电竞玩家、设计师、电子发烧友、股民...... 二、市场规模 中国电脑机箱年产量约6000万台&#xff0c;键盘年产量约3亿…