项目结构:
1)自定义PermissionRealm 继承 AuthorizingRealm 重写3个方法: getName doGetAuthorizationInfo doGetAuthenticationInfo
其中AuthenticationInfo方法请回看第(二篇)
public class PermissionRealm extends AuthorizingRealm {
public String getName() {
return "MyRealm";
}
//授权操作
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//principals:用户认证凭证信息
//SimpleAuthenticationInfo:认证方法返回封装认证信息中第一个参数,用户信息(username)
//当前登录用户名信息:用户凭证
String username= (String) principals.getPrimaryPrincipal();
//模拟查询数据库:查询用户知道的角色与权限
List<String> roles =new ArrayList<String>();
List<String> permissions =new ArrayList<String>();
//假设数据库有role1权限
roles.add("role1");
//假设数据库有user:delete权限
// permissions.add("user:delete");
permissions.add("user:*");
//返回用户在数据库中的权限与角色
SimpleAuthorizationInfo info =new SimpleAuthorizationInfo();
info.addRoles(roles);
info.addStringPermissions(permissions);
return info;
}
//认证操作
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//参数token:表示登陆时保证的UsernamePasswordToken
//通过用户名到数据库中查用户信息,封装成一个AuthenticationInfo认证对象返回,方便认证器进行对比
String username = (String) authenticationToken.getPrincipal();
//通过用户名查询数据库,讲改用户对应数据查询返回:账号与密码
//假设查询数据库返回数据为:zhangsan 666
if (!"zhangsan".equals(username)) {
return null;
}
String password = "666";
//info对象表示realm登陆对比信息,(用户名,密码,realm名字)
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());
return info;
}
}
2)配置ini文件(shiro-permission-realm.ini)
[main]
#自定义realm
myRealm=com.fxys.day05PermissionRealm.PermissionRealm
#指定Securitymanager的realm实现
securityManager.realms=$myRealm
3)加载配置文件,完成测试(测试权限请看上一章(第四篇))
public class ShiroTest {
public static void main(String[] args) {
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-permission-realm.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "666");
subject.login(token);
System.out.println("登陆是否成功" + subject.isAuthenticated());
//判断当前用户是否有某个角色的权限
System.out.println(subject.hasRole("role1"));
System.out.println(subject.isPermitted("user:list"));
}
}
流程详解:
1、首先调用Subject.isPermitted*/hasRole*接口,其会委托给SecurityManager,而SecurityManager接着会委托给Authorizer
2、Authorizer是真正的授权者,如果我们调用如isPermitted(“user:view”),其首先会通过PermissionResolver把字符串转换成相应的Permission实例;
3、在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入的角色/权限;
4、Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted*/hasRole*会返回true,否则返回false表示授权失败。