架构师一1.功能权限

1. RBAC 权限模型

系统采用 RBAC 权限模型,全称是 Role-Based Access Control 基于角色的访问控制。

简单来说,每个用户拥有多个角色,每个角色拥有多个菜单,菜单中存在菜单权限、按钮权限。这样,就形成了 “用户<->角色<->菜单” 的授权模型。 在这种模型中,用户与角色、角色与菜单之间构成了多对多的关系 

介绍完权限的设计思路接下看一下实现思路

2. Token 认证机制

安全框架使用的是 Spring Security+ Token 方案,整体流程如下图所示:

① 前端调用登录接口,使用账号密码获得到认证 Token。响应示例如下:

{"code":0,"msg":"","data":{"token":"d2a3cdbc6c53470db67a582bd115103f"}
}

管理后台的登录实现:(....省)

用户 App 的登录实现(....省)

疑问:为什么不使用 Spring Security 内置的表单登录?Spring Security 的登录拓展起来不方便,例如说验证码、三方登录等等。

Token 存储在数据库中,对应 system_oauth2_access_token 访问令牌表的 id 字段。考虑到访问的性能,缓存在 Redis 的 oauth2_access_token:%s 

疑问:为什么不使用 JWT(JSON Web Token)?JWT 是无状态的,无法实现 Token 的作废,例如说用户登出系统、修改密码等等场景。推荐阅读 《还分不清 Cookie、Session、Token、JWT?》 (opens new window)文章。

默认配置下,Token 有效期为 30 天,可通过 system_oauth2_client 表中 client_id = default 的记录进行自定义: 

  • 修改 access_token_validity_seconds 字段,设置访问令牌的过期时间,默认 1800 秒 = 30 分钟
  • 修改 refresh_token_validity_seconds 字段,设置刷新令牌的过期时间,默认 43200 秒 = 30 天
② 前端调用其它接口,需要在请求头带上 Token 进行访问。请求头格式如下:### Authorization: Bearer 登录时返回的 Token
Authorization: Bearer d2a3cdbc6c53470db67a582bd115103f
  • 具体的代码实现,可见TokenAuthenticationFilter 过滤器

考虑到使用 Postman、Swagger 调试接口方便,提供了 Token 的模拟机制。请求头格式如下:

### Authorization: Bearer test用户编号
Authorization: Bearer test1
其中 "test" 可自定义,配置项如下:### application-local.yamlyudao:security:mock-enable: true # 是否开启 Token 的模拟机制mock-secret: test # Token 模拟机制的 Token 前缀

3. 权限注解

3.1 @PreAuthorize 注解

@PreAuthorize是 Spring Security 内置的前置权限注解,添加在接口方法上,声明需要的权限,实现访问权限的控制。

① 基于【权限标识】的权限控制

权限标识,对应 system_menu 表的 permission 字段,推荐格式为 ${系统}:${模块}:${操作},例如说 system:admin:add 标识 system 服务的添加管理员。

使用示例如下:

// 符合 system:user:list 权限要求
@PreAuthorize("@ss.hasPermission('system:user:list')")// 符合 system:user:add 或 system:user:edit 权限要求即可
@PreAuthorize("@ss.hasAnyPermissions('system:user:add,system:user:edit')")

② 基于【角色标识】的权限控制

权限标识,对应 system_role 表的 code 字段, 例如说 super_admin 超级管理员、tenant_admin 租户管理员。

使用示例如下:

// 属于 user 角色
@PreAuthorize("@ss.hasRole('user')")// 属于 user 或者 admin 之一
@PreAuthorize("@ss.hasAnyRoles('user,admin')")

实现原理是什么?

当 @PreAuthorize 注解里的 Spring EL 表达式返回 false 时,表示没有权限。

而 @PreAuthorize("@ss.hasPermission('system:user:list')") 表示调用 Bean 名字为 ss 的 #hasPermission(...) 方法,方法参数为 "system:user:list" 字符串。ss 对应的 Bean 是 类,所以你只需要去看该方法的实现代码

3.2 @PreAuthenticated 注解

@PreAuthenticated是项目自定义的认证注解,添加在接口方法上,声明登录的用户才允许访问。

主要使用场景是,针对用户 App 的 /app-app/** 的 RESTful API 接口,默认是无需登录的,通过 @PreAuthenticated 声明它需要进行登录。使用示例如下:

// AppAuthController.java@PostMapping("/update-password")
@Operation(summary = "修改用户密码", description = "用户修改密码时使用")
@PreAuthenticated
public CommonResult<Boolean> updatePassword(@RequestBody @Valid AppAuthUpdatePasswordReqVO reqVO) {// ... 省略代码
}

具体的代码实现。PreAuthenticatedAspect 

4. 自定义权限配置

默认配置下,管理后台的 /admin-api/** 所有 API 接口都必须登录后才允许访问,用户 App 的 /app-api/** 所有 API 接口无需登录就可以访问。

如下想要自定义权限配置,设置定义 API 接口可以匿名(不登录)进行访问,可以通过下面三种方式:

4.1 方式一:自定义 AuthorizeRequestsCustomizer 实现

每个 Maven Module 可以实现自定义的 AuthorizeRequestsCustomizer Bean,额外定义每个 Module 的 API 接口的访问规则。例如说 yudao-module-infra 模块的 SecurityConfiguration 类,代码如下:

@Configuration("infraSecurityConfiguration")
public class SecurityConfiguration {@Value("${spring.boot.admin.context-path:''}")private String adminSeverContextPath;@Bean("infraAuthorizeRequestsCustomizer")public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {return new AuthorizeRequestsCustomizer() {@Overridepublic void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {// Swagger 接口文档registry.antMatchers("/swagger-ui.html").anonymous().antMatchers("/swagger-resources/**").anonymous().antMatchers("/webjars/**").anonymous().antMatchers("/*/api-docs").anonymous();// Spring Boot Actuator 的安全配置registry.antMatchers("/actuator").anonymous().antMatchers("/actuator/**").anonymous();// Druid 监控registry.antMatchers("/druid/**").anonymous();// Spring Boot Admin Server 的安全配置registry.antMatchers(adminSeverContextPath).anonymous().antMatchers(adminSeverContextPath + "/**").anonymous();}};}}

友情提示

  • permitAll() 方法:所有用户可以任意访问,包括带上 Token 访问
  • anonymous() 方法:匿名用户可以任意访问,带上 Token 访问会报错

如果你对 Spring Security 了解不多,可以阅读艿艿写《芋道 Spring Boot 安全框架 Spring Security 入门 》。

4.2 方式二:@PermitAll 注解

在 API 接口上添加@PermitAll注解,示例如下:

// FileController.java
@GetMapping("/{configId}/get/{path}")
@PermitAll
public void getFileContent(HttpServletResponse response,@PathVariable("configId") Long configId,@PathVariable("path") String path) throws Exception {// ...
}

4.3 方式三:yudao.security.permit-all-urls 配置项

在 application.yaml 配置文件,通过 yudao.security.permit-all-urls 配置项设置,示例如下:

yudao:security:permit-all-urls:- /admin-ui/** # /resources/admin-ui 目录下的静态资源- /admin-api/xxx/yyy

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

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

相关文章

JAVA设计模式(二)-简单工厂

JAVA设计模式(二)-简单工厂 本篇文章主要讲下java 创建型设计模式中的简单工厂模式. 简单工厂模式又叫 静态工厂方法模式&#xff08;Static FactoryMethod Pattern&#xff09;,是通过专门定义一个类来负责创建其他类的实例&#xff0c;被创建的实例通常都具有共同的父类。 …

StringBoot常用注解(不断添加)

Configuration 定义配置类&#xff0c;之前的Spring配置都是写在xml配置文件里面的。在新的Spring版本里&#xff0c;建议首要选择把配置写道配置类中。 ComponeneScan 定义扫描路径。 Bean 默认方法名讲就是bean的id&#xff0c;返回类型就是方法返回的类型。也可以Bean("…

第二十一章网络通信总结博客

网络程序设计基础 局域网与互联网 为了实现两台计算机的通信&#xff0c;必须用一个网络线路连接两台计算机。如下图所示 网络协议 1.IP协议 IP是Internet Protocol的简称&#xff0c;是一种网络协议。Internet 网络采用的协议是TCP/IP协议&#xff0c;其全称是Transmissio…

Linux 环境变量 与 命令行参数

什么是环境变量 从结构上来看&#xff0c;环境变量就是操作系统维护的一组&#xff1a;key-value 的键值对。 不知道你是否有一个疑问&#xff1a;为什么我们写代码编译链接 形成的可执行程序要运行起来需要带路径呢&#xff1f;Linux 内置的命令也是可执行程序&#xff0c;为…

Builder设计模式

我们往往不想一下子从构造方法里面把参数传递过去&#xff0c;而是一个个参数构造。此时就用到Builder设计模式。 比如&#xff1a;属性计算中&#xff0c;我们构造各个方法。

11.AUTOSAR 诊断栈分析(四)--FIM和DCM

目录 1.Event Debounce策略 2.Function Inhibition Manager 3.DCM 4.小结 前面我们用了大概三篇的篇幅描述了诊断栈的基本概念,分别如下: 8.AUTOSAR 诊断栈分析(一)-CSDN博客 9.AUTOSAR 诊断栈分析(二)-CSDN博客

html刷题笔记

1 em 12 pt 16 px 100% source元素为audio、video、picture元素指定多个媒体文件 margin是用来隔开元素与元素的间距&#xff1b;padding是用来隔开元素与内容的间隔。 margin用于布局分开元素使元素与元素互不相干&#xff1b;padding用于元素与内容之间的间隔&#xff0c;…

【前端架构】清洁前端架构

探索前端架构&#xff1a;概述与干净的前端架构相关的一些原则&#xff08;SOLID、KISS、DRY、DDD等&#xff09;。 在我之前的一篇帖子中&#xff0c;我谈到了Signals和仍然缺少的内容[1]。现在&#xff0c;我想谈谈一个更通用的主题&#xff0c;即Clean Frontend Architectu…

Mysql综合案例练习<1>

MySql综合案例练习<1> 题目一题目二题目三题目四题目五题目六题目七题目八题目九题目十题目十一题目十二题目十三题目十四题目十五题目十六题目十七题目十八题目十九 题目一 创建数据库test01_library 创建表 books&#xff0c;表结构如下&#xff1a; CREATE DATABASE …

【js】连续相同请求时,如何中断还未返回的请求

需求 前端页面&#xff0c;用户连续翻页&#xff0c;或是连续筛选这样的连续请求&#xff0c;如果保证发起一次请求时&#xff0c;去中断掉上一次还未返回的请求&#xff1f; 代码 使用axios实现 import axios from axios; import requistDuplicateBlacklist from ./requis…

量子纠缠通讯:未来通讯技术的革命性突破

量子纠缠通讯:未来通讯技术的革命性突破 引言 随着科学技术的不断发展,量子纠缠通讯已成为当今最热门的研究领域之一。作为一种革新性的通讯技术,量子纠缠通讯有望为我们的信息安全和传输速度带来前所未有的提升。那么,究竟什么是量子纠缠通讯,它的原理又是如何的呢?本…

【Hadoop-Distcp】通过Distcp的方式进行两个HDFS集群间的数据迁移

【Hadoop-Distcp】通过Distcp的方式进行两个HDFS集群间的数据迁移 1&#xff09;Distcp 工具简介及参数说明2&#xff09;Shell 脚本 1&#xff09;Distcp 工具简介及参数说明 【Hadoop-Distcp】工具简介及参数说明 2&#xff09;Shell 脚本 应用场景&#xff1a; 两个实时集…

HWL-2511-SS 路由器命令执行漏洞复现 [附POC]

文章目录 HWL-2511-SS 路由器命令执行漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现0x06 修复建议HWL-2511-SS 路由器命令执行漏洞复现 [附POC] 0x01 前言 免责声明:请勿利用文章内的相关技术从事非法测试,…

股市复苏中的明懿金汇:抓住新机遇

2023年对于明懿金汇来说是充满挑战与机遇的一年。面对复杂多变的市场环境&#xff0c;明懿金汇展现了其对市场趋势的敏锐洞察和卓越的策略适应能力。以下是该公司在2023年的主要投资策略和市场适应方式的详细分析。 随着2023年中国股市迎来反弹&#xff0c;明懿金汇迅速调整了…

Linux Docker 安装Nginx

1.21、查看可用的Nginx版本 访问Nginx镜像库地址&#xff1a;https://hub.docker.com/_/nginx 2、拉取指定版本的Nginx镜像 docker pull nginx:latest #安装最新版 docker pull nginx:1.25.3 #安装指定版本的Nginx 3、查看本地镜像 docker images 4、根据镜像创建并运行…

Shopify 开源 WebAssembly 工具链 Ruvy

最近,Spotify 开源了Ruvy,一个 WebAssembly 工具链,能够将 Ruby 代码转换为 Wasm 模块。Ruvy 基于ruby.wasm, 用 Rust 实现,提升了性能并简化了 Wasm 模块的执行。 Ruvy 利用了ruby.wasm提供的 Ruby 解释器模块,并使用wasi-vfs (WASI 虚拟文件系统)将其与所有指定的 Rub…

汽水瓶

某商店规定&#xff1a;三个空汽水瓶可以换一瓶汽水&#xff0c;允许向老板借空汽水瓶&#xff08;但是必须要归还&#xff09;。小张手上有n个空汽水瓶&#xff0c;她想知道自己最多可以喝到多少瓶汽水。 数据范围&#xff1a;输入的正整数满足 1≤n≤100 注意&#xff1a;本…

java.lang.UnsupportedOperationException解决方法

问题描述 在实际开发中经常会有类似的这种代码&#xff0c;想要按类的某一个属性对列表中的元素分组。 例如&#xff1a; 有一些学生&#xff0c;然后根绝他们的年龄对他们进行分组。可以写出如下代码。 public class UnsupportedOperationExceptionDemo {DataNoArgsConstru…

ARM Cortex-M安全之MPU介绍

ARM Cortex-M处理器系列中的存储保护单元&#xff08;Memory Protection Unit&#xff0c;简称MPU&#xff09;是一种硬件机制&#xff0c;可用于在嵌入式系统中实现存储保护和访问权限控制。MPU允许开发人员对不同的内存区域分配不同的权限&#xff0c;从而提供对系统代码和数…