shiro提供了对外验证角色和权限的API,都是通过Subject来调用。
@Test
public void auth(){
Subject subject=SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken("zhang", "123");
subject.login(token);
if(subject.hasRole("role1")){
System.out.println("have role");
}else{
System.out.println("not have role");
}
if(subject.isPermitted("user:update")){
System.out.println("have permitted");
}else{
System.out.println("not have permitted");
}
}
public boolean isPermitted(String permission) {
return hasPrincipals() && securityManager.isPermitted(getPrincipals(), permission);
}
public boolean hasRole(String roleIdentifier) {
return hasPrincipals() && securityManager.hasRole(getPrincipals(), roleIdentifier);
}
SecurityManager会委托给org.apache.shiro.authz.Authorizer
public abstract class AuthorizingSecurityManager extends AuthenticatingSecurityManager {
private Authorizer authorizer;
public AuthorizingSecurityManager() {
super();
this.authorizer = new ModularRealmAuthorizer();
}
public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {
return this.authorizer.hasRole(principals, roleIdentifier);
}
权限的验证都是委托给Authorizer接口的定义如下:
public interface Authorizer{
boolean isPermitted(PrincipalCollection principals, String permission);
boolean isPermitted(PrincipalCollection subjectPrincipal, Permission permission);
boolean[] isPermitted(PrincipalCollection subjectPrincipal, String... permissions);
boolean[] isPermitted(PrincipalCollection subjectPrincipal, List permissions);
boolean isPermittedAll(PrincipalCollection subjectPrincipal, String... permissions);
boolean isPermittedAll(PrincipalCollection subjectPrincipal, Collection permissions);
void checkPermission(PrincipalCollection subjectPrincipal, String permission) throws AuthorizationException;
void checkPermission(PrincipalCollection subjectPrincipal, Permission permission) throws AuthorizationException;
void checkPermissions(PrincipalCollection subjectPrincipal, String... permissions) throws AuthorizationException;
void checkPermissions(PrincipalCollection subjectPrincipal, Collection permissions) throws AuthorizationException;
boolean hasRole(PrincipalCollection subjectPrincipal, String roleIdentifier);
boolean[] hasRoles(PrincipalCollection subjectPrincipal, List roleIdentifiers);
boolean hasAllRoles(PrincipalCollection subjectPrincipal, Collection roleIdentifiers);
void checkRole(PrincipalCollection subjectPrincipal, String roleIdentifier) throws AuthorizationException;
void checkRoles(PrincipalCollection subjectPrincipal, Collection roleIdentifiers) throws AuthorizationException;
void checkRoles(PrincipalCollection subjectPrincipal, String... roleIdentifiers) throws AuthorizationException;
}
org.apache.shiro.authz.ModularRealmAuthorizer是SecurityManager的默认实现,直接取Realm中找,找到了就返回true。
public boolean hasRole(PrincipalCollection principals, String roleIdentifier) {
assertRealmsConfigured();
for (Realm realm : getRealms()) {
if (!(realm instanceof Authorizer)) continue;
if (((Authorizer) realm).hasRole(principals, roleIdentifier)) {
return true;
}
}
return false;
}
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
assertRealmsConfigured();
for (Realm realm : getRealms()) {
if (!(realm instanceof Authorizer)) continue;
if (((Authorizer) realm).isPermitted(principals, permission)) {
return true;
}
}
return false;
}
public class CustomRealm extends AuthorizingRealm {
/**
* 获取权限信息
* author wenyi
* time: 2017年10月9日上午9:23:43
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//登录的时候放入的用户信息
User user=(User) principals.getPrimaryPrincipal();
//伪代码,根据用户信息查到角色和权限
//.....
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
//添加角色
String role="role1";
info.addRole(role);
//添加权限
String permission="user:update";
info.addStringPermission(permission);
return info;
}
/**
*
* 进行登录认证
* author wenyi
* time: 2017年10月9日上午9:24:18
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken userToken=(UsernamePasswordToken)token;
String userName=userToken.getUsername();
//伪代码,根据token取到对应的用户信息,shiro只会比较密码是否正确,不会再比较用户名
User user=new User();
user.setUserName(userName);
//伪代码,这个是根据token查到的密码,shiro会比较登录的密码与这个密码是否一致
String password="from db";
return new SimpleAuthenticationInfo(user, password, getName());
}
}