授权概述
授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等)。
在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、 角色(Role)
-
主体
主体,即访问应用的用户,在Shiro中使用Subject代表该用户。用户只有授权后才允许访问相应的资源。 -
资源
在应用中用户可以访问的任何东西,比如访问JSP 页面、查看/编辑某些数据、访问某个业务方法、打印文本等等都是资源。用户只要授权后才能访问。 -
权限
安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的权力。即权限表示在应用中用户能不能访问某个资源,如:访问用户列表页面查看/新增/修改/删除用户数据(即很多时候都是CRUD(增查改删)式权限控制)打印文档等等。。。 -
角色
角色代表了操作集合,可以理解为权限的集合,一般情况下我们会赋予用户角色而不是权限,即这样用户可以拥有一组权限,赋予权限时比较方便。典型的如:项目经理、技术总监、CTO、开发工程师等都是角色,不同的角色拥有一组不同的权限。
授权流程
分四步:
-
Subject 发起请求,判断是否具有相应的角色或权限
-
SecurityManager 委托给Authorizer
-
Authorizer 授权器
-
Realm 查找角色和权限信息
授权
[users]
# 用户zhang的密码是zs,此用户具有role1和role2两个角色
zhangsan = zs, role1, role2
# 用户wang的密码是123,此用户具有role2角色
wang = 123, role2
# 权限
[roles]
# 角色role1对资源user拥有create、update权限
role1 = user:create, user:update
# 角色role2对资源user拥有create、delete权限
role2 = user:create, user:delete
# 角色role3对资源user拥有create权限
role3 = user:create
权限配置规则
角色权限的配置规则: 角色=权限1,权限2
权限标识符号规则:== 资源标识符:操作:实例id==
user:create:01 表示拥有对user资源的01实例进行create操作的权限。
user:create:* 表示拥有对user资源进行create操作的权限,对所有用户资源实例进行create操作。 简写:user:update
user:* : * 表示拥有user资源的所有操作权限。简写 user 或 user:*(推荐)
*:insert: * 表示拥有对所有资源插入的权限。简写 *:insert
user:*:01 表示拥有对user资源实例01进行所有操作的权限
user:insert,user:update 简写 user:insert,update
相关方法
subject.hasRole(“”); 判断是否有角色
boolean hasRole = subject.hasRole("role1"); System.out.println(hasRole);
subject.hashRoles(List);分别判断用户是否具有List中每个内容
boolean[] hasRoles = subject.hasRoles(Arrays.asList("role1", "role2"));
System.out.println(Arrays.toString(hasRoles));
subject.hasAllRoles(Collection);返回boolean,要求参数中所有角色用户都需要具有.
boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1", "role2"));
System.out.println(hasAllRoles);
subject.isPermitted(“”);判断是否具有权限.
boolean permitted = subject.isPermitted("role1:update"); System.out.println(permitted);
subject.isPermitted(List);分别判断用户是否具有List中每个权限
boolean[] permitted1 = subject.isPermitted("role1:view", "role2:view");
System.out.println(Arrays.toString(permitted1));
subject.isPermittedAll(Collection);返回boolean,要求参数中所有权限都需要具有.
boolean permittedAll = subject.isPermittedAll("role1:view", "role2:view");
System.out.println(permittedAll);
从以上的代码中可以看出我们的用户,密码,角色,权限都是在shrio.ini里面配置的,但是实际开发中肯定不是这样的,实际开发中我们的所有数据都是从数据库里面来的,如何实现呢,那就要使用数据和+自定义realm
自定义Realm实现授权
/**
* 自定义Realm实现
*/
public class UserRealm extends AuthorizingRealm {
@Override
public String getName() {
return "UserRealm";
}
//用于认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//从token中获取身份信息
String username = (String)token.getPrincipal();
//根据用户名到数据库中取出用户信息 如果查询不到 返回null
String password = "1111";//假如从数据库中获取密码为1111
//返回认证信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, this.getName());
return simpleAuthenticationInfo;
}
//用于授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//获取身份信息
String username = (String)principals.getPrimaryPrincipal();
//模拟根据身份信息获取权限数据
List<String> permissions = new ArrayList<String>();
permissions.add("user:save");
permissions.add("user:delete");
//将权限信息保存到AuthorizationInfo中
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
for(String permission:permissions){
simpleAuthorizationInfo.addStringPermission(permission);
}
return simpleAuthorizationInfo;
}
}
shiro.ini
# 自定义realm
userRealm = com.tuojun.realm.UserRealm
# 将realm设置到securityManager
securityManager.realms = $userRealm