介绍
授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、角色(Role),这是在所有的授权框架中都需要考虑的。
主体,即访问应用的用户,在 Shiro 中使用 Subject 代表该用户。用户只有授权后才允许访问相应的资源,没有权限需要根据业务逻辑做出相应的响应来优化用户体验。
资源 在应用中用户可以访问的数据、URL、页面、可以进行的操作,用户需要有权限才可进行访问。
权限 Permission是访问控制的基本单元,用于描述能够访问控制的资源对象。通过权限我们可以表示在应用中用户有没有操作某个资源的权力。Permission通常可以表示为操作或访问类型,例如创建、读取、更新、删除(CRUD)等等,授权的操作是编程人员根据业务逻辑自己进行开发,Shiro框架不会进行定义。
Shiro提供了多种实现Permission接口的方式,其中最常用的权限实现有:
- WildcardPermission:通配符权限,使用通配符’*‘表示匹配任意字符,’?'表示匹配任意单个字符。
- StringPermission:字符串权限,基于字符串匹配进行授权,比较灵活。
- BitPermission:位权限,将权限表示为一个位向量,并将每种权限定义为向量中的一位。
- RolePermission:角色权限,基于角色实现授权,如果Subject拥有某个角色,则具备相应的操作权限。
- PermissionResolver:以程序方式自定义Permission实现类,在实际应用中使用十分灵活。
Shiro 支持粗粒度权限(如用户模块的所有权限)和细粒度权限(操作某个用户的权限,即实例级别的)即判断用户有没有权限和判断用户有没有角色。
角色 角色代表了操作集合,可以理解为权限的集合,一般情况下我们会赋予用户角色而不是权限,即这样用户可以拥有一组权限,赋予权限时比较方便。
在现在开发中常用“RBAC”模式来设计权限系统,“RBAC”现在有两种解释,分别为:基于角色的访问控制 (Role-Based Access Control))”和“基于资源的访问控制(Resource-Based Access Control)”。 基于角色的访问控制属于一种控制粒度比较粗的权限设置,基于资源的访问控制控制粒度比较细等等。
授权
在Shiro中要对用户进行授权可以通过Shiro提供的ini配置文件或者是在登录成功后通过Reaml中的doGetAuthorizationInfo 方法进行授权。
ini配置
ini文件设置
Shiro框架可以通过ini配置文件进行权限角色的配置。配置文件中主要有三个部分:Section、Key和Value。其中,配置的对象用方括号[]括起来,表示一个块;Key和Value则用等号=分隔,表示键值对。 users:Section用于配置用户和密码,每一行用键值对表示一个用户,多个角色使用逗号分隔。例如,admin用户的密码是123,拥有role1,role2角色。
roles:用于配置角色和相应的权限,表示每个角色可以访问的资源。例如,admin角色可以访问所有资源,user角色只能访问/user目录下的资源。
urls:用于配置URL和访问该URL所需的角色。例如,/protected/** 表示URL通配符,authc表示访问该URL需要认证,roles[admin]表示访问该URL需要admin角色。
# 定义用户拥有的角色
[users]
# 用户名 = 密码,多个角色使用逗号分隔
admin=123,role1,role2
user=123,role1
# 定义角色拥有的权限
# 角色名 = 权限,多个权限使用逗号分隔
[roles]
role1=user:create,user:update
role2=user:create,user:delete
# 定义Url与拦截器
# URL = 角色,多个角色使用逗号分隔
[urls]
/protected/** = authc, roles[admin], perms["permission1"]
数据库操作
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
User user = (User) principalCollection.getPrimaryPrincipal();
// 数据库中查询当前用户拥有的角色
List<Role> roleList = roleservice.getRoleListByUserName(user.getUserName());
List<Permission> permissionList = null;
if (roleList.size() > 0) {
//添加角色
for (Role role : roleList) {
authorizationInfo.addRole(role.getRole());
// 通过角色查询权限
permissionList = permissionService.getPermissionListByRoleId(role.getRoleId());
for (Permission permission : permissionList) {
//添加权限
authorizationInfo.addStringPermission(permission.getPermission());
}
}
}
return authorizationInfo;
权限判断
方式一
使用JSP标签判断,判断当前用户是否拥有admin角色
<shiro:hasRole name="admin">
<!— 有权限 —>
</shiro:hasRole>
方式二
// 判断使用拥有单个角色
subject().hasRole("role1");
// 判断使用拥有多个角色
subject().hasAllRoles(Arrays.asList("role1", "role2"))
方式三
@RequiresAuthentication
表示当前 Subject 已经通过 login 进行了身份验证;即 Subject.isAuthenticated() 返回 true。
@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)
表示当前 Subject 需要角色 admin 和 user。
@RequiresPermissions (value={“user:a”, “user:b”}, logical= Logical.OR)
表示当前 Subject 需要权限 user:a 或 user:b。
等等还有很多的标签、方法、注解在这里只展示如何使用,具体的信息有兴趣的同学可以百度。