🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍
文章目录
1.0 权限系统
1.1 引入
1.2 RBAC 权限模型
1.3 数据库设计
2.0 Spring Security 核心功能-授权
2.1 思路分析
2.2 编写 SQL 语句
2.3 将用户权限进行封装
2.4 获取用户权限
2.5 启动预授权
3.0 自定义异常处理器
4.0 自定义校验权限方法
在 Java 开发中,Spring Security 是一个非常强大的框架,用于处理应用程序的安全性。它不仅提供了认证(Authentication)功能,还提供了授权(Authorization)功能,确保用户只能访问他们被授权的资源。
Spring Security 框架中对认证功能进行介绍:
Spring Security 框架篇-深入了解 Spring Security 的认证功能流程和自定义实现登录接口(实现自定义认证过滤器、登出功能)-CSDN博客
Spring Security 的授权功能主要围绕着几个核心概念构建:
1)权限(Permissions):
权限是最低级别的安全控制,通常与特定的操作或资源相关联。例如,read、write、delete等权限可以被分配给特定的数据对象或业务操作。
2)角色(Roles):
角色是一组权限的集合。在应用中,通常会根据职责的不同来定义不同的角色,如管理员、普通用户、访客等。每个角色拥有一系列权限,这些权限定义了该角色可以执行的操作。
3)访问决策管理器(Access Decision Manager):
这个组件负责决定是否允许请求访问受保护的资源。它基于配置的策略(如一致同意、多数同意等)来评估所有相关的权限和角色。
4)投票者(Voters):
投票者是访问决策管理器的一部分,它们根据用户的权限对访问请求进行投票。投票结果影响最终的访问决策。
5)方法安全(Method Security):
Spring Security 提供了在方法级别上实现细粒度安全控制的能力。通过使用注解如 @PreAuthorize 和 @PostAuthorize,可以为特定的方法调用设置访问控制规则。
6)URL 安全(URL Security):
通过配置 HTTP 请求的安全性,可以限制对特定 URL 模式的访问。这通常是通过在 HttpSecurity 配置中定义匹配模式和相应的访问规则来实现的。
RBAC,即基于角色的访问控制,是一种广泛使用的安全模型,它将权限与角色关联起来,而不是直接与用户关联。这样做的好处包括但不限于:
简化管理:通过管理少量的角色及其权限,而不是大量的个人用户权限,大大减少了管理工作量。
提高灵活性:当组织结构或业务需求发生变化时,可以通过调整角色和权限来快速适应,而不需要逐个修改用户权限。
增强安全性:通过最小权限原则,每个用户只拥有完成其工作所需的最少权限,从而减少潜在的安全风险。
在 Spring Security 中实现 RBAC 模型通常涉及以下步骤:
定义角色:根据应用的需求定义不同的角色。
分配权限:为每个角色分配适当的权限。
用户角色映射:将用户与一个或多个角色关联起来。
配置安全策略:利用 Spring Security 提供的工具(如 @Secured 注解、@PreAuthorize 表达式等)来定义哪些角色可以访问哪些资源或执行哪些操作。
通过这种方式,Spring Security 可以有效地支持复杂的权限管理和访问控制需求,帮助开发者构建更加安全可靠的应用程序。
如果将其分解进行数据库设计,RBAC0基本模型可以分成以下五个部分:
1)User(用户):每个用户都有唯一的UID识别,并被授予不同的角色
2)Role(角色):不同角色具有不同的权限
3)Permission(权限):访问权限
4)用户-角色映射:用户和角色之间的映射关系
5)角色-权限映射:角色和权限之间的映射
转换成数据库表的话大致如下所示:
这就可以实现给用户进行授权相关的权限。
根据业务需求,对数据库进行设计:
在登录验证过程中,即在实现 UserDetailsService 接口的 MyUserDetailService 实现类里面除了将用户的基本信息进行封装返回,还需要将用户的权限信息也要进行封装返回。
以用户 "xbs" 为例子:
当然可以直接通过多个表关联查询,这里将 SQL 分开是为了更好梳理用户、角色、权限之间的关系。
由于需要封装到 LoginUser 类中,则添加 List<String> permissions 成员变量来存放权限信息,且为了其他类可以获取到这些权限信息,还需要重写 getAuthorities() 方法,返回权限信息。
如果其他类频繁的调用 getAuthorities() 方法来获取权限信息,就会重复的进行封装 GrantedAuthority 实体类,因此,当 authorities 不为 Null,说明之前已经被调用 getAuthorities() 方法来获取权限信息,现在直接可以从 authorities 实体获取权限信息即可。
这里需要注意的是因为 SimpleGrantedAuthority 无法序列化,如果直接使用,fastjson 转换时就会出错,即 Redis 存取时会运行异常,因此我们需要使用 @JSONField 关闭其序列化;
MyUserDetailService 类:
在登录认证中,需要获取用户权限,且将用户权限存放到 SecurityContextHolder 容器中,方便在后续的过滤器进行权限校验。
在 MySecurityFilter 登录认证过滤器中,验证成功之后,将获取的用户权限加载到 SecurityContextHolder 容器,在后续的 FlterSecurityInterceptor 权限校验器中进行校验,如果校验失败则会抛出 403 异常。
代码如下:
MySecurityFilter 登录认证过滤器
Spring Security 为我们提供了基于注解的权限控制方案,可以使用注解去指定访问对应的资源所需的权限,需要手动开启,在 SecurityConfig 配置类上开启预授权功能。
在开启了预授权之后,就可以使用 @PreAuthorize 注解对接口进行权限控制了,该注解中使用 SPEL 表达式进行权限配置,表达式中的参数为权限名,对应我们获取的 perms 权限集合。
举个例子:
使用 @PreAuthorize 注解,调用 hasAuthority("权限标识") 方法,如果该用户存在该权限,则返回 true,证明该用户有权限访问该接口;如果该用户不存在该权限,则返回 false,说明该用户不存在该权限,不允许访问当前接口。
相关源码:
这写着认证授权时我们会发现有些地方我们是手动抛了异常的,但是为什么在返回的数据中并没有我们想要的数据呢?
这是因为在 Spring Security 中默认对抛出的异常进行了捕获并对其进行了处理,因此就会返回上图中的数据。但是没明显我们并不是很想让他返回这种数据,而是在抛异常时也能返回我们的统一返回格式,这样可以让前端能对响应进行统一的处理。要实现这个功能我们需要知道 Spring Security 的异常处理机制。
在 Spring Security 过滤链中,可以通过重写相关的方法来自定义异常处理器。
1)对于登录验证过程中抛出的异常:
需要实现 AuthenticationEntryPoint 接口,重写 commence() 方法,从而来手动自定义异常处理器。
这个可以使用统一返回格式,使用 Result 对象封装好相关的信息,然后通过 httpServletResponse.getWriter() 方法得到 PrintWriter 对象,再由该对象调用 write() 方法写到客户端。
举个简单的例子,这里就直接返回字符串给客户端了。
2)对于授权验证过程中抛出的异常:
需要实现 AccessDeniedHandler 接口,重写 handle() 方法。
在编写完成对应的处理器之后,需要配置给 Spring Security 框架,让框架使用我们自定义的异常处理器,这同样是在 SecurityConfig 配置类中的 configure 方法进行配置。
SecurityConfig 配置类:
在 Spring Security 框架中,一般是通过 @PreAuthorize("hasAuthority('权限标识')") 这种方法来进行校验的,也可以手动自定义来创建校验权限的方法,会更加灵活。
首先定义一个实体类,且将该类交给 IOC 容器成为 Bean 对象:
在 SecurityContextHolder 容器中获取用户权限信息,直接调用 getPermissions() 方法获取到权限集合。接着判断用户权限集合是否包含当前接口所需要的权限 authority 。
然后在 @PreAuthorize 注解中调用该类的方法即可:
到此这篇rbac 权限(rbac 权限去重)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rfx/71633.html