架构
核心是SecurityManager
认证是通过调用Authenticator来实现的,authenticator内部又是调用realm的doGetAuthenticationInfo实现
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
assertRealmsConfigured();
Collection<Realm> realms = getRealms();
if (realms.size() == 1) {
return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
} else {
return doMultiRealmAuthentication(realms, authenticationToken);
}
}
doSingleRealmAuthentication
AuthenticationInfo info = realm.getAuthenticationInfo(token);
info = doGetAuthenticationInfo(token);
//SimpleAccountRealm.java
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;
}
//拿到AuthenticationInfo后使用assertCredentialsMatch(token,info)进行账户、密码比对
public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo info = getCachedAuthenticationInfo(token);
if (info == null) {
//otherwise not cached, perform the lookup:
info = doGetAuthenticationInfo(token);
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;
}
//assertCredentialsMatch(token,info)内部又调用了SimpleCredentialsMatcher.doCredentialsMatch比对
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
Object tokenCredentials = getCredentials(token);
Object accountCredentials = getCredentials(info);
return equals(tokenCredentials, accountCredentials);
}
同理,授权也是通过调用authorizer来实现,authorize内部调用realm的doGetAuthorizationInfo实现
认证
package com.twx.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;
public class AuthenticationTest {
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
@Before
public void addUser(){
simpleAccountRealm.addAccount("mark","123456");
}
@Test
public void testAuthentication(){
//1.构建SecruityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
//2. 主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("mark","123456");
subject.login(token);
System.out.println("isAuthenticated: "+subject.isAuthenticated());
subject.logout();
System.out.println("isAuthenticated: "+subject.isAuthenticated());
}
}
授权
package com.twx.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;
public class AuthenticationTest {
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
@Before
public void addUser(){
simpleAccountRealm.addAccount("mark","123456","admin","dev");
}
@Test
public void testAuthentication(){
//1.构建SecruityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
//2. 主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("mark","123456");
subject.login(token);
System.out.println("isAuthenticated: "+subject.isAuthenticated());
// subject.checkRole("admin");
subject.checkRoles("admin","dev");
subject.logout();
System.out.println("isAuthenticated: "+subject.isAuthenticated());
}
}