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数据模型实现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中,目前博主使用版本较低是这么配置,后面高级版本的配置应该会简单很多,使用一些注解就能够达到我们的需求了,后面有空的话可能会出一篇公司的版本控制方案和操作。
- 上一篇:Spring Security(十四):基于JWT实现SSO单点登录
- 下一篇:敬请期待~