IniRealm的类结构如下图:
下面分析每个类:
(1)Ream:
域的顶点,其代码如下:securityManager会使验证器来调用,验证器通过Realm返回用户信息,确定用户是否登录成功:
1 public interface Realm { 2 String getName();//返回Realm的名字,唯一 3 boolean supports(AuthenticationToken token);//校验token 4 AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;//返回用户信息 5 }
(2) CachingRealm:
缓存域,支持用户信息的缓存:可以注入缓存器,支持Realm名字的修改,支持用户的登出:
1 public abstract class CachingRealm implements Realm, Nameable, CacheManagerAware, LogoutAware { 2 private String name; 3 private boolean cachingEnabled;//支持缓存,默认为true 4 private CacheManager cacheManager; //注入缓存器 5 public CachingRealm() { 6 this.cachingEnabled = true; 7 this.name = getClass().getName() + "_" + INSTANCE_COUNT.getAndIncrement(); 8 } 9 ........... 10 public void setCacheManager(CacheManager cacheManager) { 11 this.cacheManager = cacheManager; 12 afterCacheManagerSet(); 13 } 14 public void onLogout(PrincipalCollection principals) { 15 clearCache(principals); 16 } 17 18 ........ 19 }
(3)AuthenticatingRealm:
验证器的域,可以注入缓存器,主要是实现CachingRealm扩展的子接口,并支持初始化,doGetAuthenticationInfo(token),由子类实现,
public abstract class AuthenticatingRealm extends CachingRealm implements Initializable { private CredentialsMatcher credentialsMatcher;//密码匹配器 private Cache<Object, AuthenticationInfo> authenticationCache;//用户信息的缓存,相当一个Map集合,用户名={AuthenticationInfo,.....} public AuthenticatingRealm() { this(null, new SimpleCredentialsMatcher()); } public AuthenticatingRealm(CacheManager cacheManager, CredentialsMatcher matcher) { authenticationTokenClass = UsernamePasswordToken.class; //retain backwards compatibility for Shiro 1.1 and earlier. Setting to true by default will probably cause //unexpected results for existing applications: this.authenticationCachingEnabled = false;//是否验证器的缓存 int instanceNumber = INSTANCE_COUNT.getAndIncrement(); this.authenticationCacheName = getClass().getName() + DEFAULT_AUTHORIZATION_CACHE_SUFFIX; if (instanceNumber > 0) { this.authenticationCacheName = this.authenticationCacheName + "." + instanceNumber; } if (cacheManager != null) { setCacheManager(cacheManager);//设置缓存器 } if (matcher != null) { setCredentialsMatcher(matcher); } }
//实现Realm的获取验证信息 public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { AuthenticationInfo info = getCachedAuthenticationInfo(token);//从缓存中获取 if (info == null) { //otherwise not cached, perform the lookup: info = doGetAuthenticationInfo(token);//子类实现,或者自定义的realm里面自己实现 log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info); if (token != null && info != null) { cacheAuthenticationInfoIfPossible(token, info);//压入到缓存 } } else { log.debug("Using cached authentication info [{}] to perform credentials matching.", info); } if (info != null) { assertCredentialsMatch(token, info); } else { log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token); } return info; } protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException; public boolean supports(AuthenticationToken token) { return token != null && getAuthenticationTokenClass().isAssignableFrom(token.getClass()); } ........ public final void init() { //trigger obtaining the authorization cache if possible getAvailableAuthenticationCache(); onInit(); } }
(4)AuthorizingRealm:
权限认证器,实现AuthenticatingRealm,Authorizer(用来做权限检查)、PermissionResolverAware(支持自定义的权限解析)、RolePermissionResolverAware(支持自定义的角色权限解析)
public abstract class AuthorizingRealm extends AuthenticatingRealm implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware { private boolean authorizationCachingEnabled;// private Cache<Object, AuthorizationInfo> authorizationCache; private String authorizationCacheName; private PermissionResolver permissionResolver;
private RolePermissionResolver permissionRoleResolver;
public AuthorizingRealm() {
this(null, null);
}
public AuthorizingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
super();
if (cacheManager != null) setCacheManager(cacheManager);
if (matcher != null) setCredentialsMatcher(matcher);
this.authorizationCachingEnabled = true;//默认为true
this.permissionResolver = new WildcardPermissionResolver();//创建权限解析器
int instanceNumber = INSTANCE_COUNT.getAndIncrement();
this.authorizationCacheName = getClass().getName() + DEFAULT_AUTHORIZATION_CACHE_SUFFIX;
if (instanceNumber > 0) {
this.authorizationCacheName = this.authorizationCacheName + "." + instanceNumber;
}
}
}
//获取权限信息
protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
........
Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();//先从缓存中获取
info = doGetAuthorizationInfo(principals);//如果缓存没有,则获取原数据
if (info == null) {
// Call template method if the info was not found in a cache
info = doGetAuthorizationInfo(principals);//
// If the info is not null and the cache has been created, then cache the authorization info.
if (info != null && cache != null) {
if (log.isTraceEnabled()) {
log.trace("Caching authorization info for principals: [" + principals + "].");
}
Object key = getAuthorizationCacheKey(principals);
cache.put(key, info);
}
}
return info;
}
//权限判断的例子
public boolean[] isPermitted(PrincipalCollection subjectIdentifier, String... permissions) {
List<Permission> perms = new ArrayList<Permission>(permissions.length);
for (String permString : permissions) {
perms.add(getPermissionResolver().resolvePermission(permString));
}
return isPermitted(subjectIdentifier, perms);
}
//权限之间的判断
private boolean isPermitted(Permission permission, AuthorizationInfo info) {
Collection<Permission> perms = getPermissions(info);
if (perms != null && !perms.isEmpty()) {
for (Permission perm : perms) {
if (perm.implies(permission)) {
return true;
}
}
}
return false;
}
........
(5)、SimpleAccountRealm:
是对AuthorizingRealm的一个身份验证,主要实现doGetAuthenticationInfo、doGetAuthorizationInfo新口
public class SimpleAccountRealm extends AuthorizingRealm { protected final Map<String, SimpleAccount> users; //username-to-SimpleAccount protected final Map<String, SimpleRole> roles; //roleName-to-SimpleRole protected final ReadWriteLock USERS_LOCK; protected final ReadWriteLock ROLES_LOCK;
public SimpleAccountRealm() {
this.users = new LinkedHashMap<String, SimpleAccount>();
this.roles = new LinkedHashMap<String, SimpleRole>();
USERS_LOCK = new ReentrantReadWriteLock();
ROLES_LOCK = new ReentrantReadWriteLock();
//SimpleAccountRealms are memory-only realms - no need for an additional cache mechanism since we're
//already as memory-efficient as we can be:
setCachingEnabled(false);
}
//获取用户信息
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
SimpleAccount account = getUser(upToken.getUsername());
if (account != null) {
if (account.isLocked()) {
throw new LockedAccountException("Account [" + account + "] is locked.");
}
if (account.isCredentialsExpired()) {
String msg = "The credentials for account [" + account + "] are expired";
throw new ExpiredCredentialsException(msg);
}
}
return account;
}
//获取权限器信息
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = getUsername(principals);
USERS_LOCK.readLock().lock();
try {
return this.users.get(username);
} finally {
USERS_LOCK.readLock().unlock();
}
}
//增加用户信息
protected void add(SimpleAccount account) {
String username = getUsername(account);
USERS_LOCK.writeLock().lock();
try {
this.users.put(username, account);
} finally {
USERS_LOCK.writeLock().unlock();
}
}
}
(6)TextConfigurationRealm:
主要继承自SimpleAccountRealm,用来配置SimpleAccountRealm的Map<String, SimpleAccount> users,和 Map<String, SimpleRole> roles
//增加roles protected void processRoleDefinitions(Map<String, String> roleDefs) { if (roleDefs == null || roleDefs.isEmpty()) { return; } for (String rolename : roleDefs.keySet()) { String value = roleDefs.get(rolename); SimpleRole role = getRole(rolename); if (role == null) { role = new SimpleRole(rolename); add(role); } Set<Permission> permissions = PermissionUtils.resolveDelimitedPermissions(value, getPermissionResolver()); role.setPermissions(permissions); } } //增加users protected void processUserDefinitions(Map<String, String> userDefs) { if (userDefs == null || userDefs.isEmpty()) { return; } for (String username : userDefs.keySet()) { String value = userDefs.get(username); String[] passwordAndRolesArray = StringUtils.split(value); String password = passwordAndRolesArray[0]; SimpleAccount account = getUser(username); if (account == null) { account = new SimpleAccount(username, password, getName()); add(account); } account.setCredentials(password); if (passwordAndRolesArray.length > 1) { for (int i = 1; i < passwordAndRolesArray.length; i++) { String rolename = passwordAndRolesArray[i]; account.addRole(rolename); SimpleRole role = getRole(rolename); if (role != null) { account.addObjectPermissions(role.getPermissions()); } } } else { account.setRoles(null); } } }
(7)IniRealm,
通过配置ini来定义user,和role:如:
private void processDefinitions(Ini ini) { if (CollectionUtils.isEmpty(ini)) { log.warn("{} defined, but the ini instance is null or empty.", getClass().getSimpleName()); return; } Ini.Section rolesSection = ini.getSection(ROLES_SECTION_NAME);//定义全局的role(role包含perm) if (!CollectionUtils.isEmpty(rolesSection)) { log.debug("Discovered the [{}] section. Processing...", ROLES_SECTION_NAME); processRoleDefinitions(rolesSection); } Ini.Section usersSection = ini.getSection(USERS_SECTION_NAME); if (!CollectionUtils.isEmpty(usersSection)) { log.debug("Discovered the [{}] section. Processing...", USERS_SECTION_NAME); processUserDefinitions(usersSection);//配置用户的acount,user,perm } else { log.info("{} defined, but there is no [{}] section defined. This realm will not be populated with any " + "users and it is assumed that they will be populated programatically. Users must be defined " + "for this Realm instance to be useful.", getClass().getSimpleName(), USERS_SECTION_NAME); } }
总结:
不解之处有:
SimplePrincipalCollection的 Map<String, Set> realmPrincipals的定义,为什么用Set集合保存Principals