鲁春利的工作笔记,好记性不如烂笔头
Shiro配置文件(shiro-customize-permission.ini)
[main] myRealmA=com.invicme.apps.shiro.permission.MyRealmOne myPermissionResolver=com.invicme.apps.shiro.permission.MyPermissionResolver securityManager.authorizer.permissionResolver = $myPermissionResolver securityManager.realms=$myRealmA
com.invicme.apps.shiro.permission.MyPermissionResolver
package com.invicme.apps.shiro.permission; import org.apache.log4j.Logger; import org.apache.shiro.authz.Permission; import org.apache.shiro.authz.permission.PermissionResolver; import org.apache.shiro.authz.permission.WildcardPermission; /** * * @author lucl * */ public class MyPermissionResolver implements PermissionResolver { private static final Logger logger = Logger.getLogger(MyPermissionResolver.class); /** * @param permissionString * @return */ @Override public Permission resolvePermission(String permissionString) { logger.info("The method resolvePermission(" + permissionString + ") was invoke."); if(permissionString.indexOf("+") != -1) { return new MyPermission(permissionString); } return new WildcardPermission(permissionString); } }
com.invicme.apps.shiro.permission.MyPermission
package com.invicme.apps.shiro.permission; import java.io.Serializable; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.log4j.Logger; import org.apache.shiro.authz.Permission; /** * * @author lucl * */ public class MyPermission implements Permission, Serializable { private static final Logger logger = Logger.getLogger(MyPermission.class); /** * */ private static final long serialVersionUID = 1L; protected static final String PART_DIVIDER_TOKEN = "\\+"; // 需转义,否则split报错 protected static final boolean DEFAULT_CASE_SENSITIVE = false; private String domain = ""; private String action = ""; private String instanceId = ""; public MyPermission () { // ...... } public MyPermission (String permissionString) { this(permissionString, DEFAULT_CASE_SENSITIVE); } public MyPermission (String permissionString, boolean caseSensitive) { logger.info("The constructor MyPermission () was invoke."); setParts(permissionString, caseSensitive); } private void setParts(String permissionString, boolean caseSensitive) { if (StringUtils.isBlank(permissionString)) { permissionString = ""; } if (caseSensitive) { permissionString = permissionString.toLowerCase(); } String[] parts = permissionString.split(PART_DIVIDER_TOKEN); if (null != parts && parts.length == 3) { domain = parts[0]; action = parts[1]; instanceId = parts[2]; } } @Override public boolean implies(Permission p) { logger.info("The method implies() was invoke."); if (!(p instanceof MyPermission)) { return false; } MyPermission that = (MyPermission) p; if (this.domain.equals(that.domain) && this.action.equals(that.action) && this.instanceId.equals(that.instanceId)) { return true; } return false; } @Override public String toString() { return ReflectionToStringBuilder.toString(this); } }
com.invicme.apps.shiro.permission.MyRealmOne
package com.invicme.apps.shiro.permission; import org.apache.log4j.Logger; 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; /** * * @author lucl * */ public class MyRealmOne extends AuthorizingRealm { private static final Logger logger = Logger.getLogger(MyRealmOne.class); @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { logger.info("The method doGetAuthenticationInfo() was invoke."); String principal = String.valueOf(token.getPrincipal()); // 得到身份(用户名) String credentials = new String((char[])token.getCredentials()); // 得到认证/凭证(密码) SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, this.getClass().getName()); return info; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { logger.info("The method doGetAuthorizationInfo() was invoke."); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); /** * 只有当SimpleAuthorizationInfo中设置了权限后,自定义的Permission中implies方法才会被调用。 */ info.addStringPermission("system+edit+10"); return info; } }
@Test public void testCustomizePermission () { // 1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro/permission/shiro-customize-permission.ini"); // 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("lucl", "123"); try{ // 4、登录,即身份验证(会调用MyRealmOnde的doGetAuthenticationInfo方法) subject.login(token); } catch (AuthenticationException e) { // 5、身份验证失败 logger.info("用户身份验证失败"); e.printStackTrace(); } // 用户身份得到确认 if (subject.isAuthenticated()) { logger.info("用户登录成功。"); /** * 进行权限判断 */ logger.info("-----------------------Begin-------------------------"); // isPermitted方法会调用MyRealmOne的doGetAuthorizationInfo()方法 boolean hasPermission1 = subject.isPermitted("system+edit+10"); logger.info("The user has permission system+edit+10 is " + hasPermission1); // true logger.info("------------------------End------------------------"); logger.info("-----------------------Begin-------------------------"); // isPermitted方法会调用MyRealmOne的doGetAuthorizationInfo()方法 boolean hasPermission3 = subject.isPermitted("users+delete+1"); // false logger.info("The user has permission users+delete+1 is " + hasPermission3); // true logger.info("------------------------End------------------------"); } else { logger.info("用户登录失败。"); } // 6、退出 subject.logout(); }
总结:
自定义Realm继承AuthorizingRealm 而不是实现Realm 接口;推荐使用AuthorizingRealm,因
为:
AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token):表示获取身份验证信
息;
AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals):表示根据用户身份
获取授权信息。