1、授权
授权,即访问控制,控制谁能访问哪些资源。主体进行身份认证后需要分配权限方可访问系统的资源,对于某些资源没有权限是无法访问的。
2、关键对象
授权可简单理解为who对what(which)进行How操作
who,即主体(sbuject),主体需要访问系统中的资源。
what,资源(resource),如菜单,页面,按钮,类方法,系统商品信息。
how,权限/许可(permission),规定了主体对资源的操作许可,通过权限可知主体对那些资源有操作许可。crud权限
3、授权流程
授权的流程是基于用户合法的访问
4、授权方式
基于角色的访问
if(subject.hasRole("admin")){ //操作什么资源 }
基于资源的访问控制
if(subject.isPermission("user:update:01")){ //资源实例 //对01资源拥有修改权限 } if(subject.isPermission("user:update:*")){ //对所有资源,拥有update权限 } if(subject.isPermission("user:*:01")){ //资源实例 //对01资源拥有所有权限 }
5、授权字符串
权限字符串的规则是:资源标识符:操作:资源实例标识符,意思是对哪个资源的哪个实例具有什么操作,“:”是资源/操作/实例的分割符,权限字符串也可以使用*通配符。
用户创建权限:user:create,或user:create:* 用户修改实例001的权限:user:update:001 用户实例001的所有权限:user:*:001
6、shiro实现方式
编程式
Subject subject = SecurityUtils.getSubject(); if(subject.hasRole("admin")) { //有权限 }else { //无权限 }
标签式
@RequiresRoles("admin") public void hello() { //有权限 }
标签式
Jsp/GSp标签,在jsp/GSp页面通过相应的标签完成 <shiro:hasRole name="admin"> <!--有权限--> </shiro:hasRole>
注意:Thymeleaf中使用shiro需要额外集成!
7、授权案例
CustomerRealm授权域,添加授权角色、授权资源
package com.demo.grant; 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 CustomerRealm extends AuthorizingRealm { //授权方法 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //获取主要身份 String primaryPrincipal = (String) principals.getPrimaryPrincipal(); System.out.println("primaryPrincipal = " + primaryPrincipal); //根据身份信息 用户名 获取当前用户的角色信息,以及权限信息 xiaochen admin user SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //将模拟数据库中查询角色信息赋值给权限对象 simpleAuthorizationInfo.addRole("admin"); simpleAuthorizationInfo.addRole("user"); //将数据库中查询权限信息赋值给权限对象 //对用户下01实例具有所有权限 这是资源路径实例 simpleAuthorizationInfo.addStringPermission("user:*:01"); //对product下一切资源实例具有创建权限,*可以省略 simpleAuthorizationInfo.addStringPermission("product:create"); return simpleAuthorizationInfo; } //认证方法 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String principal = (String) token.getPrincipal(); if("zhangsan".equals(principal)){ //模拟数据库中已经md5加盐处理过的密码 String password = "efe2cdcad63be25838e3847becd43df4"; String salt = "x0*&p"; //需要这个解开密码 return new SimpleAuthenticationInfo(principal,password, ByteSource.Util.bytes(salt),this.getName()); } return null; } }
测试类
package com.demo.md5; 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.mgt.DefaultSecurityManager; import org.apache.shiro.subject.Subject; public class TestAuthenticatorCusttomerRealm { public static void main(String[] args) { //创建securityManager DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); //IniRealm realm = new IniRealm("classpath:shiro.ini"); //设置为自定义realm获取认证数据 CustomerRealm customerRealm = new CustomerRealm(); //设置md5加密 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); credentialsMatcher.setHashAlgorithmName("MD5"); //添加加密字符串 credentialsMatcher.setHashIterations(1024);//设置散列次数 打乱顺序 customerRealm.setCredentialsMatcher(credentialsMatcher); //MD5加密器//设置自定义realm defaultSecurityManager.setRealm(customerRealm); //将自定义的realm设置到安全管理中 //将安装工具类中设置默认安全管理器 SecurityUtils.setSecurityManager(defaultSecurityManager); //将安全管理设置到安全工具中 //获取主体对象 Subject subject = SecurityUtils.getSubject(); //创建token令牌 UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123"); try { //subject对象 中方法 +加盐 +验证+权限操作 主体对象调用login方法 subject.login(token);//用户登录,shiro会自动将token中的password在自定义realm中加上盐去处理 System.out.println("登录成功~~"); } catch (UnknownAccountException e) { e.printStackTrace(); System.out.println("用户名错误!!"); }catch (IncorrectCredentialsException e){ e.printStackTrace(); System.out.println("密码错误!!!"); } } }
效果
登录成功~~ primaryPrincipal = zhangsan true primaryPrincipal = zhangsan primaryPrincipal = zhangsan 这是用户=======false primaryPrincipal = zhangsan primaryPrincipal = zhangsan primaryPrincipal = zhangsan true false true ===================================================== primaryPrincipal = zhangsan 权限资源判断=====true primaryPrincipal = zhangsan 权限true primaryPrincipal = zhangsan primaryPrincipal = zhangsan true false primaryPrincipal = zhangsan primaryPrincipal = zhangsan true