《跟我学shiro》的第28页到30页,写得是使用位操作算法实现权限匹配,但是在验验过程中初学者会做得不太顺利,原因是教材中的代码不全。为了通俗易懂,我把这个实验过程全部笔录一遍,并说明原理。
先来认识几个单词:
authorizer 【奥得ruai热】 [经] 核准人,授权人, 在shiro中它是授权API的入口。
permission 【拍米生】 允许;批准,正式认可,认可, 在shiro中,它就是最后要得到的权限。resolver 【瑞肉喂】 下决心者,解决[答]问题者;溶媒;求解仪。
PermissionResolver 在shiro中,它是根据通配符解析成权限。
RolePermissionResolver 在shiro它是根据角色解析成权限。
第一步:新建一个shiro_6的maven工程;
第二步:修改成UTF-8编码;
第三步:写pom.xml,内容如下:
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>0.2.23</version> </dependency> </dependencies>第四步:写src/main/resource下写shiro的配置文件:shiro.ini,内容如下:
[main] #授权入口 authorizer=org.apache.shiro.authz.ModularRealmAuthorizer #采用解析Bit字符串得到权限 permissionResolver=www.jintingbo.com.BitAndWildPermissionResolver authorizer.permissionResolver=$permissionResolver #根据角色得到角色的权限 rolePermissionResolver=www.jintingbo.com.MyRolePermissionResolver authorizer.rolePermissionResolver=$rolePermissionResolver securityManager.authorizer=$authorizer realm=www.jintingbo.com.MyRealm securityManager.realms=$realm第五步:写BitAndWildPermissionResolver类
看上面的配置,因为这个类不是shiro内部有的,所以要自己写。代码如下:
public class BitAndWildPermissionResolver implements PermissionResolver { public Permission resolvePermission(String permissionString) { if (permissionString.startsWith("+")) { return new BitPermission(permissionString); } return new WildcardPermission(permissionString); } }注意这个类中有一个BitPermission类也可自己写。代码如下:
public class BitPermission implements Permission { private String resourceIdentify; private int permissionBit; private String instanceId; public BitPermission(String permissionString) { String[] array = permissionString.split("\\+"); if (array.length > 1) { resourceIdentify = array[1]; } if (StringUtils.isEmpty(resourceIdentify)) { resourceIdentify = "*"; } if (array.length > 2) { permissionBit = Integer.valueOf(array[2]); } if (array.length > 3) { instanceId = array[3]; } if (StringUtils.isEmpty(instanceId)) { instanceId = "*"; } } public boolean implies(Permission p) { //判断权限匹配 if (!(p instanceof BitPermission)) { return false; } BitPermission other = (BitPermission) p; if (!("*".equals(this.resourceIdentify) || this.resourceIdentify .equals(other.resourceIdentify))) { return false; } if (!(this.permissionBit == 0 || (this.permissionBit & other.permissionBit) != 0)) { return false; } if (!("*".equals(this.instanceId) || this.instanceId .equals(other.instanceId))) { return false; } return true; } }第六步:写MyRolePermissionResolver类
public class MyRolePermissionResolver implements RolePermissionResolver { public Collection<Permission> resolvePermissionsInRole(String roleString) { if("role1".equals(roleString)) { return Arrays.asList((Permission)new WildcardPermission("menu:*")); } return null; } }第七步:写MyRealm,这一部分,教材上的代码不全,所以在这里加上它的验证部分。
public class MyRealm extends org.apache.shiro.realm.AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.addRole("role1"); authorizationInfo.addRole("role2"); authorizationInfo.addObjectPermission(new BitPermission("+user1+10")); authorizationInfo.addObjectPermission(new WildcardPermission("user1:*")); authorizationInfo.addStringPermission("+user2+10"); authorizationInfo.addStringPermission("user2:*"); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { String username = (String)token.getPrincipal(); //得到用户名 String password = new String((char[])token.getCredentials()); //得到密码 if(!"zhang".equals(username)) { throw new UnknownAccountException(); //如果用户名错误 } if(!"123".equals(password)) { throw new IncorrectCredentialsException(); //如果密码错误 } //如果身份认证验证成功,返回一个 AuthenticationInfo 实现; return new SimpleAuthenticationInfo(username, password, getName()); } public String getName() { return "aaa"; } public boolean supports(AuthenticationToken arg0) { return arg0 instanceof UsernamePasswordToken; } }第八步:写测试运行的类
public class MyTest { private static void login(String configFile,String username,String password) { //1、获取 SecurityManager 工厂,此处使用 Ini 配置文件初始化 SecurityManager Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory(configFile); //2、得到 SecurityManager 实例 并绑定给 SecurityUtils org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); //3、得到 Subject 及创建用户名/密码身份验证 Token(即用户身份/凭证) Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username,password); subject.login(token); } public static void main(String[] args) { login("classpath:shiro.ini","zhang","123"); Subject subject = SecurityUtils.getSubject(); try{ subject.isPermitted("system:menu111:view"); System.out.println("OK!"); }catch (UnauthorizedException e){ System.out.println("没有这个权限!"); } }
}
第九步:运行
完毕
QQ:14280784
