Spring Security(十五):基于RBAC数据模型的权限控制

Spring Security官方文档是这么介绍的:Spring Security是一个功能强大且高度可定制的身份认证和访问控制框架。我们花了十多个篇幅都是在认证授权方面,而它的另一个重要的特点就是访问控制。这一篇我们就来讲讲关于它的内容。

权限控制

容易混淆的概念

  • 首先,和前端功能权限控制是不一样的。
  • 前端功能权限哪些角色有哪些权限,只是在页面按钮是否置灰或者是否显示一些功能方面进行控制,不同角色有哪些功能。
  • 而且我们这篇讲解的是后台接口的访问权限控制,也就是在后台层面对不同角色访问不同接口有不同权限限制。

前面文章涉及到的权限控制

举例

  • 其实从一开始我们就接触到了,比如说哪些接口不需要登录就可以访问(登录接口等等)。如下主配置文件中的配置项:
	.authorizeRequests()
		// 排除对 "/authentication/require" 和 "/meicloud-signIn.html" 等的身份验证
		.antMatchers("/authentication/require", securityProperties.getBrowser().getSignInPage(), "/code/*")
		.permitAll()
		// 表示所有请求
		.anyRequest()
		// 需要身份验证
		.authenticated()
		.and()

权限表达式

  • 上面.permitAll()表示权限表达式,如下还有很多可以使用的权限表达式
权限表达式 说明
permitAll 表示允许所有,永远返回true
denyAll 表示拒绝所有,永远返回false
anonymous 当前用户是anonymous时返回true
rememberMe 当前用户是rememberMe用户时返回true
authenticated 当前用户不是anonymous时返回true
fullyAuthenticated 当前用户既不是anonymous也不是rememberMe用户时返回true
hasRole 用户拥有指定权限时返回true
hasAnyRole([role1, role2]) 用于拥有任意一个角色权限时返回true
hasAuthority 用户拥有指定权限时返回true
hasAnyAuthority([authority1, authority2]) 用户拥有任意一个指定权限时返回true
hasIpAddress(‘192.168.1.0/24’) 请求发送的Ip匹配时返回true
  • 可以查看代码中有哪些权限表达式可以使用
    可选权限表达式

基于RBAC数据模型的权限控制

  • 当然上面只是Spring Security提供的一些方便操作的权限控制表达式。在实际的项目中,有各种各样的角色,不同角色又有不同权限,这个时候如何设计呢?

RBAC数据模型

  • 全称:Role-Based Access Control(基于角色的访问控制)
  • 一般会有五个表组成,三张主体表(用户、角色、权限),两张关联表(用户-角色、角色-权限)
  • 图解
    RBAC数据模型

基于RBAC数据模型实现Spring Security的权限控制

  • 定义RbacService接口
public interface RbacService {
    
    
	boolean hasPermission(HttpServletRequest request, Authentication authentication);
}
  • 定义它的实现类RbacServiceImpl,其实所有当前用户拥有的权限都是在登录授权的时候设置进了authentication中
@Component("rbacService")
public class RbacServiceImpl implements RbacService {
    
    

	private AntPathMatcher antPathMatcher = new AntPathMatcher();

	@Override
	public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
    
    
		Object principal = authentication.getPrincipal();
		boolean hasPermission = false;

		if (principal instanceof Admin) {
    
    
			// 如果用户名是admin,就永远返回true
			if (StringUtils.equals(((Admin) principal).getUsername(), "admin")) {
    
    
				hasPermission = true;
			} else {
    
    
				// 读取用户所拥有权限的所有URL
				Set<String> urls = ((Admin) principal).getUrls();
				for (String url : urls) {
    
    
					if (antPathMatcher.match(url, request.getRequestURI())) {
    
    
						hasPermission = true;
						break;
					}
				}
			}
		}
		return hasPermission;
	}
}
  • 应用进Spring Security中,创建配置类实现AuthorizeConfigProvider接口
@Component
public class DemoAuthorizeConfigProvider implements AuthorizeConfigProvider {
    
    
	@Override
	public boolean config(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry config) {
    
    
		//demo项目授权配置
		return false;
	}
}
  • 其实,主要就是两点,一点要注意的是登录角色的权限需要在登录的时候查询出来并且设置到Authentication中,另外就是要自己去写关于如何拦截匹配不同接口的访问权限,还有一点就是如何配置进Spring Security中,目前博主使用版本较低是这么配置,后面高级版本的配置应该会简单很多,使用一些注解就能够达到我们的需求了,后面有空的话可能会出一篇公司的版本控制方案和操作。

猜你喜欢

转载自blog.csdn.net/qq_36221788/article/details/106977555