授权:即访问控制,控制谁能够访问哪些资源。主体进行身份认证后需要分配权限方可访问系统的资源,对于没有授权的资源则是无法访问的。
对于授权可以理解为谁对哪些资源进行什么操作,授权中的关键对象如下:
示例如下:
//基于角色的访问控制
if(subject.hasRole("admin")){
//操作资源
}
//基于资源的角色控制
if(subject.isPermission("user:update:01")){
//拥有对01用户的修改权限
}
if(subject.isPermission("user:update:*")){
//拥有对所有用户的修改权限
}
权限字符串是以字符串的方式实现对授权规则的表示,其规则是:资源标识符:操作:资源实例标识符,意思是对哪个资源的哪个实例具有什么操作,:是资源/操作1/实例的分隔符,权限字符串也可以使用*作为通配符。示例如下:
用户创建权限:user:create,或user::create:*
用户修改实例为001的权限:user:update:001
用户拥有实例001的所有权限:user:*:001
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole("admin")){
//有权限
}else{
//无权限
}
@RequiresRoles("admin")
public void hello(){
//有权限
}
方法说明如下:
方法名
说明
hasRole
是否具有某个角色
hasAllRole
是否具有所有角色
hasRoles
分别具有哪些角色
代码:
package org.example.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import java.util.Arrays;
public class TestMD5 {
// 21232f297a57a5a743894a0e4a801fc3
// a5599b5184c1aadc0877cd76cb93a969
// 578422679b493529e22c5495c8b3db3c
public static void main(String[] args) {
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
//注入realm
UserMD5Realm realm = new UserMD5Realm();
//设置realm使用hash凭证匹配器
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("md5");
//设置散列次数
credentialsMatcher.setHashIterations(1024);
realm.setCredentialsMatcher(credentialsMatcher);
//设置Realm
defaultSecurityManager.setRealm(realm);
//将安装工具类中设置默认安全管理器
SecurityUtils.setSecurityManager(defaultSecurityManager);
//获取主体对象
Subject subject = SecurityUtils.getSubject();
//创建token令牌
UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin");
try{
//用户登录
subject.login(token);
System.out.println("登陆成功");
}catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("用户名错误");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码错误");
}
//认证成功
if(subject.isAuthenticated()){
System.out.println(subject.hasRole("拥有的角色"));
//hasRole判断是否具有某种角色
System.out.println("hasRole方法");
if(subject.hasRole("admin")){
System.out.println("admin拥有管理员角色");
}else{
System.out.println("admin没有管理员角色");
}
//hasAllRoles判断是否同时具有这些角色
System.out.println("hasAllRoles方法");
if(subject.hasAllRoles(Arrays.asList("admin", "super", "users"))){
System.out.println("admin拥有管理员、超级管理员和用户角色");
}else{
System.out.println("admin不同时具有这些角色");
}
//hasRoles是否具有其中一个角色
System.out.println("hasRoles方法");
boolean[] roles = subject.hasRoles(Arrays.asList("admin", "super", "users"));
for(boolean b : roles){
System.out.println(b);
}
}
}
}
package org.example.shiro;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
public class UserMD5Realm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
//根据身份信息 用户名获取当前用户的角色信息和权限信息,这一块从数据库中读取。
//本案例中,我们假设admin用户具有管理员权限和普通用户的角色
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addRole("admin");
simpleAuthorizationInfo.addRole("users");
return simpleAuthorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取身份信息
String principal = (String) authenticationToken.getPrincipal();
if("admin".equals(principal)){
//这里的密码模拟是从数据库中读到的
String password = "578422679b493529e22c5495c8b3db3c";
return new SimpleAuthenticationInfo(principal, password, ByteSource.Util.bytes("vasdg"), this.getName());
}
return null;
}
}
方法说明如下:
方法名
说明
isPermitted
是否具有某个权限
isPermitted
是否具有其中部分角色,前一个方法的重载
isPermittedAll
是否具有所有角色
代码:
基于上述代码加入以下逻辑:
TestMD5的主方法
//具有某种权限
System.out.println("是否具有对01用户的修改权限 : " + subject.isPermitted("user:update:01"));
//分别具有哪些权限
boolean[] permitted01 = subject.isPermitted("user:*:01", "order:update:01");
for(boolean b : permitted01){
System.out.println(b);
}
//同时具有哪些权限
boolean permitted02 = subject.isPermittedAll("user:*:01", "order:update:01");
System.out.println(permitted02);
UserMD5Realm的doGetAuthorizationInfo()方法:
//基于权限字符串的访问控制
simpleAuthorizationInfo.addStringPermission("user:*:01");
simpleAuthorizationInfo.addStringPermission("product:create:01");