spring security 中的授权使用

news2024/12/23 10:39:07

一、认证

    身份认证,就是判断一个用户是否为合法用户的处理过程。Spring Security 中支持多种不同方式的认证,但是无论开发者使用那种方式认证,都不会影响授权功能使用。因为 SpringSecurity 很好做到了认证和授权解耦。

 

二、授权

    授权,即访问控制,控制谁能访问哪些资源。简单的理解授权就是根据系统提前设置好的规则,给用户分配可以访问某一个资源的权限,用户根据自己所具有权限,去执行相应操作。

2.1权限管理核心概念

     我们得知认证成功之后会将当前登录用户信息保存到Authentication 对象中,Authentication 对象中有一个getAuthorities() 方法,用来返回当前登录用户具备的权限信息,也就是当前用户具有权限信息。该方法的返回值为 Collection<?extends GrantedAuthorit,当需要进行权限判断时,就回根据集合返回权限信息调用相应方法进行判断。

2.2 GrantedAuthority 解释

 

    那么问题来了,针对于这个返回值 GrantedAuthority 应该如何理解呢? 是角色还是权限?

我们针对于授权可以是 基于角色权限管理 和 基于资源权限管理 ,从设计层面上来说,角色和权限是两个完全不同的东西: 权限是一些具体操作,角色则是某些权限集合。如:READ_BOOK 和 ROLE_ADMIN 是完全不同的。因此至于返回值是什么取决于你的业务设计情况:。基于角色权限设计就是: 用户 => 角色 => 资源  三者关系 返回就是用户的 角色。基于资源权限设计就是:用户e=>双限<=>资源”三者关系 返回就是用户的 权限。基于角色和资源权限设计就是: 用户角色<>权限<>资源 返回统称为用户的 权限为什么可以统称为权限,因为从代码层面角色和权限没有太大不同都是权限,特别是在Spring Security中,角色和权限处理方式基本上都是一样的。唯一区别 SpringSecurity在很多时候会自动给角色添加一个 ROLE_前缀,而权限则不会自动添加。

 

2.3 权限管理策略

 

Spring Security 中提供的权限管理策略主要有两种类型:

1)、基于过滤器(URL)的权限管理(FilterSecurityinterceptor)

           基于过滤器的权限管理主要是用来拦截 HTTP 请求,拦截下来之后,根据 HTTP 请求地址进行权限校验。

2)、基于AOP 的权限管理 (MethodSecurityinterceptor)

        基于AOP 权限管理主要是用来处理方法级别的权限问题。当需要调用某一个方法时,通过AOP 将操作拦截下来,然后判断用户是否具备相关的权限。

2.3.1 基于URL 权限管理

  在配置中写死,/** 需要有xx角色或者权限才能访问

2.3.1.1 准备工作

 

 1)pom.xml 依赖包

 2)测试controller

 3)security 配置

我们在controller中创建了三个方法,分别为

/adminInf   这个url(可以匹配 /adminInf.   /adminInf/  /adminInf.htm 等等)需要拥有admin的角色才能访问

/rootInf  这个url 需要拥有root的角色才能访问

/getUser 这个url 需要拥有read:user的权限才能才能访问

2.3.1.2 security 配置

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    /**
     *  定义自己的userDetail
     *
     */
    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager im = new InMemoryUserDetailsManager();
        im.createUser(User.withUsername("admin").password("{noop}123").roles("admin","root").build());
        im.createUser(User.withUsername("root").password("{noop}123").roles("root").build());
        im.createUser(User.withUsername("test").password("{noop}123").authorities("read:user").build());
        return im;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .mvcMatchers("/adminInf").hasRole("admin") // /adminInf 这个url下面必须有 admin的角色才能访问
                .mvcMatchers("/rootInf").hasAnyRole("admin","root") // /rootInf 这个url下面 有 admin 或者root 角色均可以访问
                .mvcMatchers("/getUser").hasAnyAuthority("read:user") // /getUser 这个url 下面必须有 read:user 这个权限才能访问
                .anyRequest().authenticated()
                .and()
                .formLogin()// 开启form表单登录
                .and().csrf().disable();
    }
}

2.3.1.3 测试controller

@RestController
public class HelloController {


    @GetMapping("/getUser")
    public String getUser() {
        return "userinfo authority ok ";
    }


    @GetMapping("/adminInf")
    public String admin() {
        return "admin role ok ";
    }


    @GetMapping("/rootInf")
    public String root() {
        return "root role ok ";
    }
}

2.3.1.4 测试结果

         1)、当我们登录admin 的用户时候访问,因为getUser没有配置权限,所以不能访问

7af3a7a0ad2445a788f6fd7da722af03.png

e8c37ed31867412381b5aa506fb8d49e.png

6328b9110ff344729794be73d6e45e7c.png

        2)、当我们登录test 的用户时候访问,因为rootinfo/ adminInfo没有配置角色,所以不能访问

ef84193f4c9943e8bccf36aa7c176174.png

cb7f6258d8b8449cb8c2f6e7d7c533aa.png

f687ec1ae1984c9c8b19236bb5624725.png

 

 

2.3.1.5 基于多种匹配规则

 

MvcMatchersAuthorizedUrl 、mvcMatchers 基于mvc 的匹配规则

 /test     可以匹配  /test.   /test/   /test.h...   多种

 

org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry#antMatchers(java.lang.String...)

.antMatchers()  早期 4.0 之前使用,基于全路径匹配

 /test     只能匹配  /test  这个路径下的方法

 

从用法上来看两个使用基本没有区别,区别主要是在于匹配的路径上,mvc 可以匹配范围更广,ant 是全匹配

org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry#regexMatchers(java.lang.String...)  基于正则方案,当我们写一个正则表达式就可以

049d8c078fb14b1ab376643dbf426180.png

 


2.4 基于方法的权限管理

     基于方法的权限管理主要是通过AOP 来实现的,Spring Security 中通过

MethodSecuritvInterceptor 来提供相关的实现。不同在于Filter Security interceptor 只是在请

求之前进行前置处理,MethodSecuritvinterceptor 除了前置处理之外还可以进行后置处理。

前置处理就是在请求之前判断是否具备相应的权限,后置处理则是对方法的执行结果进行二

次过滤。前置处理和后置处理分别对应了不同的实现类。

2.4.1 开启注解支持

@EnableGlobalMethodSecurity

3aeb81066f054d8aaf1d654c270da102.png

1)、perPostEnabled: 开启 Spring Security 提供的四个权限注解,@PostAuthorize

@PostFilter、@PreAuthorize 以及 @PreFilter。

2)、securedEnabled: 开启 Spring Security 提供的 @Secured 注解支持,该注解不支持权限表达式

3)、jsr250Enabled:开启JSR-250 提供的注解,主要是@DenyAll、@PermitAll、@RolesAll 同

样这些注解也不支持权限表达式

# 以上注解含义如下:

- @PostAuthorize: 在日标方法执行之后进行权限校验。

- @PostFiter: 在目标方法执行之后对方法的返回结果进行过滤。

- @PreAuthorize: 在目标方法执行之前进行权限校验。

- @PreFiter: 在日标方法执行之前对方法参数进行过滤

- @secured: 访问目标方法必须具各相应的角色

- @DenyA11: 拒绝所有访问。

- @PermitA1l: 允许所有访问。

- @RolesAllowed: 访问目标方法必须具备相应的角色

这些基于方法的权限管理相关的注解,一般来说只要设置 prePostEnabled=true 就够用了

 

2.4.2 权限表达式

e064275f9bcf42cca6becb50a9b74289.png

 

 

2.4.3 角色权限实战

1) 

    /**

     *  登录用户必须是  admin  而且角色必须是 ADMIN

     * @return

     */

    @PreAuthorize("hasRole('ADMIN') and authentication.name == 'admin'")

    @RequestMapping("hello")

    public String hello() {

        return "hello";

    }

4cf981fe5feb47709b465c8fb01cbfc8.png


2)、

    /**

     *  登录的用户名必须和传过来的用户名一致才能通过  spe 表达式

     * @param username

     * @return

     */

    @PreAuthorize("authentication.name == #username")

    @RequestMapping("username")

    public String username(String username) {

        return "hello:" + username;

}

e005bcd5189f4673b03211a13f6e2bbc.png


3)、

    /**

     *  过滤 users 对象里面的属性  id % 2 的数据,保留 不能整除的

     *  users 必须是一个集合,否则没法过滤  filterObject 固定写法

     * @param users

     * @return

     */

    @PreFilter(value = "filterObject.id % 2 != 0",filterTarget = "users")

    @RequestMapping("users")

    public String addUser(@RequestBody List<SecurityUser> users) {

        System.out.println(users);

        try {

            String userStr = new ObjectMapper().writeValueAsString(users);

            return userStr;

        } catch (JsonProcessingException e) {

            e.printStackTrace();

        }

        return "null ";

}

9b91e1103d1c441d809c55b398d144ed.png

ab343a982db24d99a87a88aa6a00fab7.png


4、    

   /**

     *  后置过滤   当请求过来的  id值为1的时候,那么就返回,否则就不返回

     * @param id

     * @return

     */

    @PostAuthorize(value = "returnObject.id ==1 ")

    @RequestMapping("getUserId")

    public SecurityUser getUserId(Integer id) {

       return new SecurityUser(id,"lq");

}

98e1c1e7d27d4822acc3725a15235a6d.png


5)

   /** 

     *  保留  id % 2 ==0 的数据返回,用来对方法返回值进行过滤

     * @return

     */

    @PostFilter(value = "filterObject.id %2==0 ")

    @RequestMapping("getAllUser")

    public List<SecurityUser> getAllUser() {

        List<SecurityUser> userList = new ArrayList<>();

        IntStream.rangeClosed(0,10)

                .forEach(index -> userList.add(new SecurityUser(index,"lq-"+index)));

 

        return userList;

 

    }

96722f9266e34d858930921018521df1.png

jsr250 使用比较少的,因为功能比较单一

/**
 *  只能判断角色,而且需要自己加前缀  ROLE_     当前用户必须有 ADMIN 权限才能查看
 * @return
 */
@Secured({"ROLE_ADMIN"})
@RequestMapping(value = "getUser1")
public SecurityUser getUser1() {
    return new SecurityUser(1,"lisi");
}


/**
 *  判断用户有  ADMIN或者 ROOT 角色就可以访问
 * @return
 */
@Secured({"ROLE_ADMIN","ROLE_ROOT"})
@RequestMapping(value = "getUser2")
public SecurityUser getUser2() {
    return new SecurityUser(1,"王五");
}


/**
 *  所有的用户都可以访问
 * @return
 */
@PermitAll
@RequestMapping(value = "permitAll")
public String perAll() {
    return "permitAll ok ";
}


/**
 *  所有的用户都拒绝访问
 * @return
 */
@DenyAll
@RequestMapping(value = "denyAll")
public String denyAll() {
    return "denyAll ok ";
}



/**
 *  判断用户有  ADMIN或者 ROOT 角色就可以访问
 * @return
 */
@RolesAllowed({"ROLE_ADMIN","ROLE_ROOT"})
@RequestMapping(value = "rolesAllowed")
public String rolesAllowed() {
    return "rolesAllowed ok ";
}

 

 

三、授权原理分析

 

 3.1 AccessDecisionManager

(访问决策管理器),用来决定此次访问是否被允许

56edef3ce0334557a7c3117da53dae06.png

 

3.2 AccessDecisionVoter

(访问决定投票器),投票器会检查用户是否具备应有的角色,进而投出赞成、反对或者弃权票。

6b041841af084d20b4e3994166f1a07d.pngAccesDecisionVoter和AccessDecisionManager 都有众多的实现类,在 AccessDecisionManager 中会换个遍历 AccessDecisionVoter,进而决定是否允许用户访问,因而 AaccesDecisionVoter 和 AccessDecisionManager 两者的关系类似于 AuthenticationProvider 和ProviderManager 的关系。

 

3.3 ConfigAttribute

用来保存授权时的角色信息

b1b94722d7614961859ae149b489faaf.png

   在 Spring Security 中,用户请求一个资源(通常是一个接口或者一个 Java 方法)需要的角色会被封装成一个 ConfigAttribute 对象,在configAttribute 中只有一个 getAttribute方法,该方法返回一个 Strng 字符串,就是角色的名称。一般来说,角色名称都带有一个 ROLE_前缀,投票器 AccessDecisionVoter 所做的事情,其实就是比较用户所具各的角色和请求某个资源所需的 ConfigAtuibute 之间的关系。

3.4 核心类 FilterSecurityInterceptor

db245317e7e84a7fbbf82ffca734c891.png

 

3.4.1 源码

        

org.springframework.security.web.access.intercept.FilterSecurityInterceptor

        org.springframework.security.web.access.intercept.FilterSecurityInterceptor#invoke

                         org.springframework.security.access.intercept.AbstractSecurityInterceptor#beforeInvocation

                        org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource#getAttributes

org.                                springframework.security.access.intercept.AbstractSecurityInterceptor#attemptAuthorization

9a89057254494904b0d84888dd82a459.png

 

3.4.2  SecurityMetadataSource

后期可以实现这个类,自定义过滤规则,我们下一章讲解动态从数据库如何配置,以及重写这个类的实现        

fa1358e18d9b48f485f7ce35b0670f85.png

47688253bce94646aca4434e0c253e21.png

 


 

四、我们自己的角色如何放进去

我们通过参考

org.springframework.security.core.userdetails.User 类中的roles方法

0a0e211df1084fe99693b5c30ffa5892.png

 

4.1 代码实现

 // 获取权限信息 todo:后期从数据库查询

List<String>perList=Arrays.asList("new:query", "news:delete"); 

#角色 我们将这两个角色加上前缀

List<String>roles=Arrays.asList("ADMIN","USER");

List<String>roleList=roles.stream().map(r ->"ROLE_"+ r).collect(Collectors.toList());

 perList.addAll(roleList);

 

LoginSessionUserInf loginSessionUserInf=new LoginSessionUserInf(tUserInf, perList);

89717c79b7ca45228114e35641e4f94f.png

 

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

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

相关文章

红黑树的旋转

红黑树的基本性质 红黑树与普通的二叉搜索树不同&#xff0c;它在每个节点上附加了一个额外的属性——颜色&#xff0c;该颜色可以是红色或黑色。通过引入这些颜色&#xff0c;红黑树能够维持以下 5 个基本性质&#xff0c;以确保树的平衡性&#xff1a; 每个节点是红色或黑色…

C++入门10——stack与queue的使用

目录 1.什么是stack&#xff1f; stack的使用 2.什么是queue&#xff1f; queue的使用 3.priority_queue 3.1 什么是priority_queue? 3.2 priority_queue的使用 1.什么是stack&#xff1f; 在官网中&#xff0c;对stack有这样的介绍&#xff1a; Stacks are a type o…

一台电脑对应一个IP地址吗?‌探讨两台电脑共用IP的可能性

在当今数字化时代&#xff0c;‌IP地址作为网络世界中的“门牌号”&#xff0c;‌扮演着至关重要的角色。‌它负责在网络上唯一标识每一台设备&#xff0c;‌使得数据能够在庞大的互联网中准确无误地传输。‌然而&#xff0c;‌对于IP地址与电脑之间的对应关系&#xff0c;‌许…

uni-appH5项目实现导航区域与内容区域联动效果

一、需求描述 将导航区域与内容区域实现联动&#xff0c;即点击导航区域&#xff0c;内容区滚动到对应位置&#xff0c;内容区滚动过程中根据内容定位到相对应的导航栏。 效果如下&#xff1a; 侧边导航与内容联动效果 二、功能实现思路分析汇总&#xff1a; 三、具体代码 1…

Matplotlib通过axis()配置坐标轴数据详解

坐标轴范围设置 axis()可以直接传入列表[xmin,xmax,ymin,ymax]进行范围设置, 分别可以使用plt.axis()或者画布对象.axis()进行配置 import numpy as np import matplotlib.pyplot as pltx np.linspace(0, 20, 100) y x*2 plt.plot(x, y, r) plt.axis([0,30,0,100]) plt.sa…

【精选】文件摆渡系统:跨网文件传输的安全与效率之选

文件摆渡系统可以解决哪些问题&#xff1f; 文件摆渡系统&#xff08;File Shuttle System&#xff09;主要是应用于不同网络、网段、区域之间的文件数据传输流转场景&#xff0c; 用于解决以下几类问题&#xff1a; 文件传输问题&#xff1a; 大文件传输&#xff1a;系统可…

云服务器内网穿透连接云手机配置ALAS

文章目录 服务器安装TailscaleNAT网络&#xff08;无独立IP&#xff09;云服务器安装Tailscale有固定IP的云服务器安装Tailscale 云手机安装Tailscale开启无线网络调试安装Tailscale ALAS连接云手机 上次写到服务器连接云手机时只说了有独立IP的&#xff0c;但有独立IP的云手机…

IDM 工具下载 地图高程数据

巧用IDM工具 快捷下载ASTER GDEM v3高程数据 ASTER GDEM v3是NASA推出的30米高清DEM,覆盖了几乎全部的地球陆地。那么,在NASA官网怎么下载ASTER GDEM v3的地形高程数据呢? 首先,你需要注册一个nasa的账号 注册网址: https://urs.earthdata.nasa.gov/users/new 注册方式和国…

彩虹数字屏保时钟 芝麻时钟开启个性化的时代 屏保怎么能少它

彩虹数字屏保时钟 芝麻时钟开启个性化的时代 屏保怎么能少它&#xff1f;电脑屏保多样化&#xff0c;让大家有了更多的选择&#xff0c;让更多人有机会把自己的电脑打扮得漂漂亮亮&#xff0c;今天小编给大家推荐&#xff1a;芝麻时钟&#xff08;官网下载地址&#xff1a;http…

vulhub GhostScript 沙箱绕过(CVE-2018-16509)

1.执行以下命令启动靶场环境并在浏览器访问 cd vulhub/ghostscript/CVE-2018-16509 #进入漏洞环境所在目录 docker-compose up -d #启动靶场 docker ps #查看容器信息 2.访问网页 3.下载包含payload的png文件 vulhub/ghostscript/CVE-2018-16509/poc.png at master vulh…

TYPE-C USB设计

目录 摘要 TYPE-C电路 握手过程 USB电路 摘要 TYPE-C,是USB的一种接口&#xff0c;USB的第一种接口为常见的USB接口&#xff0c;U盘即为这种接口&#xff1b;第二种接口的形状类似一个凸字&#xff0c;常应用在打印机中&#xff0c;第三种接口即为TYPE-C&#xff0c;支持正…

JdbcRowSetImpl利用链分析

文章目录 JdbcRowSetImpl利用链前言JdbcRowSetImpl利用链分析 JdbcRowSetImpl利用链 前言 首先说明一下&#xff1a;利用链都有自己的使用场景&#xff0c;要根据场景进行选择不同的利用链。 JdbcRowSetImpl利用链用于fastjson反序列化漏洞中。 为什么&#xff1f; 因为fa…

暑期档总结:哪部国漫年番表现更优?

“暑期档”可能是所有档期中绵延时间最长的&#xff0c;作为该时间段主力的学生人群&#xff0c;在学业压力较小的假期中&#xff0c;需要更多娱乐方式来填充生活。除了电影之外&#xff0c;动画番剧越来越成为这一群体的不二选择&#xff0c;各个动画制作公司也会选择把精彩剧…

html记账本改写:数据重新布局,更好用了,没有localStorage保存版本

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>htm记账本</title><style>table {user-select: none;/* width: 100%; */border-collapse: collapse;}table,th,td {border: 1px solid …

RISC-V架构下 DSA - AI算力的更多可能性:Banana Pi BPI-F3 进迭时空

AI已经从技术走向应用&#xff0c;改变了我们的生活和工作方式。近些年&#xff0c;AI算力芯片领域群雄逐鹿&#xff0c;通过对芯片、算力与AI三者发展迭代过程的理解&#xff0c;我们发现高能效比的算力、通用的软件栈以及高度优化的编译器&#xff0c;是我们的AI算力产品迈向…

稚晖君同款 clion嵌入式开发环境搭建

前言 前段时间看到稚晖君的单片机开发环境&#xff0c;感觉挺酷的&#xff0c;自己也想尝试下&#xff0c;这里记录下安装过程。 安装文件准备 stm32cubemx安装 stm32cubemx stm32cubemx下载地址 当前时间是2024年9月4日&#xff0c;下载的版本是6.12.0版本&#xff0c;下…

一、关系模型和关系代数,《数据库系统概念》,原书第7版

文章目录 [toc]一、引言1.1 什么是数据库1.2 数据完整性1.3 数据库的操作1.4 数据库的持久性1.5 数据库管理系统1.6 数据模型1.7 早期DBMS 二、关系模型2.1 什么是关系模型2.2 关系数据库的结构2.3 键2.4 约束2.5 数据操纵语言(DML)2.6 关系代数2.6.1 选择运算2.6.2 投影运算2.…

【南方科技大学】CS315 Computer Security 【Lab1 Packet Sniffing and Wireshark】

目录 IntroductionBackgroundTCP/IP Network StackApplication LayerTransport LayerInternet LayerLink LayerPacket Sniffer Getting WiresharkStarting WiresharkCapturing PacketsTest Run Questions for the Lab Introduction 实验的第一部分介绍数据包嗅探器 Wireshark。…

2024高教社杯全国大学生数学建模竞赛B题原创python代码

以下均为python代码。先给大家看看之前文章的部分思路&#xff1a; 接下来我们将按照题目总体分析-背景分析-各小问分析的形式来 1 总体分析 题目提供了一个电子产品生产的案例&#xff0c;要求参赛者建立数学模型解决企业在生产过程中的一系列决策问题。以下是对题目的总体…

Cortex-A7:简单中断处理(不可嵌套中断)机制

0 参考资料 ARM Cortex-A(armV7)编程手册V4.0.pdf ARM体系结构与编程第2版1 前言 Cortex-M系列内核MCU中断硬件原生支持嵌套中断&#xff0c;开发者不需要为了实现嵌套中断而进行额外的工作。但在Cortex-A7中&#xff0c;硬件原生是不支持嵌套中断的&#xff0c;这从Cortex-A…