​http://shiro.apache.org/tutorial.html​​ 跟着教程学习如何验证你的身份,先是简单的身份验证


shiro.ini

[users]
zhang=123
wang=123

重点内容

@Test
public void testHelloworld() {
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<org.apache.shiro.mgt.SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro.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("zhang", "123");

try {
//4、登录,即身份验证
subject.login(token);
} catch (AuthenticationException e) {
//5、身份验证失败
}

Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
//6、退出
subject.logout();
}

1 跟着源码看看加载工厂,看看加载工厂的流程,有很多的设计思想,好久没看设计模式了,反正就是面向接口编程

factory

public interface Factory<T> {

T getInstance();
}

看到没有,这里用到了模板模式,其实也不太算吧,模板是按照某种运行的模式进行运行,给继承的子类,扩展的机会,这样可以按照我们的思路进行处理。

protected abstract T createInstance();

public abstract class AbstractFactory<T> implements Factory<T> {

private boolean singleton;
private T singletonInstance;

public AbstractFactory() {
this.singleton = true;
}

public boolean isSingleton() {
return singleton;
}

public void setSingleton(boolean singleton) {
this.singleton = singleton;
}

public T getInstance() {
T instance;
if (isSingleton()) {
if (this.singletonInstance == null) {
this.singletonInstance = createInstance();
}
instance = this.singletonInstance;
} else {
instance = createInstance();
}
if (instance == null) {
String msg = "Factory 'createInstance' implementation returned a null object.";
throw new IllegalStateException(msg);
}
return instance;
}

protected abstract T createInstance();
}

这里通过之前读取配置文件信息获取到的Ini类的信息(从配置文件中获取的信息),用来初始化securityManager,如果没有初始化默认的配置信息,这里在一次给子类来创建信息,和之前的写法类似

public abstract class IniFactorySupport<T> extends AbstractFactory<T> {

public static final String DEFAULT_INI_RESOURCE_PATH = "classpath:shiro.ini";

private Ini ini;

protected IniFactorySupport() {
}

protected IniFactorySupport(Ini ini) {
this.ini = ini;
}
public Ini getIni() {
return ini;
}
public void setIni(Ini ini) {
this.ini = ini;
}
public static Ini loadDefaultClassPathIni() {
Ini ini = null;
if (ResourceUtils.resourceExists(DEFAULT_INI_RESOURCE_PATH)) {
ini = new Ini();
ini.loadFromPath(DEFAULT_INI_RESOURCE_PATH);
if (CollectionUtils.isEmpty(ini)) {

}
}
return ini;
}
protected Ini resolveIni() {
Ini ini = getIni();
if (CollectionUtils.isEmpty(ini)) {
ini = loadDefaultClassPathIni();
}
return ini;
}

public T createInstance() {
Ini ini = resolveIni();
T instance;
if (CollectionUtils.isEmpty(ini)) {
log.debug("No populated Ini available. Creating a default instance.");
instance = createDefaultInstance();
if (instance == null) {
String msg = getClass().getName();
throw new IllegalStateException(msg);
}
} else {
log.debug("Creating instance from Ini [" + ini + "]");
instance = createInstance(ini);
if (instance == null) {
String msg = getClass().getName();
throw new IllegalStateException(msg);
}
}

return instance;
}

protected abstract T createInstance(Ini ini);

protected abstract T createDefaultInstance();
}

Ini 就是把配置文件信息读取出来的一个处理类。

Shiro身份认证流程,securityManager源码解析_apache

IniSecurityManagerFactory 工程继续继承 IniFactorySupport继续处理,这个就是我们初始化的最后个工厂类的信息

//举个简单的吧,Ini创建的太复杂了,需要初始化很多的信息,这里就是创建默认的工厂
protected SecurityManager createDefaultInstance() {
return new DefaultSecurityManager();
}
//然后看看这个默认的DefaultSecurityManager管家,看看继承图片,发现为什么管家有很多的功能!它管理着所有Subject、且负责进行认证和授权、及会话、缓存的管理。全部都被继承进来了,通过SecurityManager接口就可以创建无缝的对接啊,太强大了。下面的成员中看看成员就知道了,啥子意思了。
protected RememberMeManager rememberMeManager;
protected SubjectDAO subjectDAO;
protected SubjectFactory subjectFactory;
/**
* Default no-arg constructor.
*/
public DefaultSecurityManager() {
super();
this.subjectFactory = new DefaultSubjectFactory();
this.subjectDAO = new DefaultSubjectDAO();
}

Shiro身份认证流程,securityManager源码解析_apache_02

这里的管家都是基本上利用代理模式处理,而且代理的全部都是接口,还有就是留了很多的函数,当调用父类设置的时候,同时调用子类的处理函数,很高端的用法–模板方法,在设计模式中有的

public abstract class CachingSecurityManager
implements SecurityManager, Destroyable,
CacheManagerAware {

/**
* The CacheManager to use to perform caching operations to enhance performance. Can be null.
*/
// 这里就是代理模式,创建一个成员变量,在里面使用当前接口的实现类的信息
//都是使用接口处理,太牛了
private CacheManager cacheManager;


public CachingSecurityManager() {
}


public CacheManager getCacheManager() {
return cacheManager;
}

/**
* Sets the CacheManager used by this {@code SecurityManager} and potentially any of its
* children components.
* <p/>
* After the cacheManager attribute has been set, the template method
* {@link #afterCacheManagerSet afterCacheManagerSet()} is
executed to allow subclasses to adjust when a
* cacheManager is available.
* 看到没有这里就是模板方法啊,调用子类的信息哦!哈哈,一种非常高级的技能
* @param cacheManager the CacheManager used by this
{@code SecurityManager} and potentially any of its
* children components.
*/
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
afterCacheManagerSet();
}

/**
* Template callback to notify subclasses that a
* {@link org.apache.shiro.cache.CacheManager CacheManager}
has been set and is available for use via the
* {@link #getCacheManager getCacheManager()} method.
*/
protected void afterCacheManagerSet() {
}

/**
* Destroys the {@link #getCacheManager() cacheManager}
via {@link LifecycleUtils#destroy LifecycleUtils.destroy}.
*/
public void destroy() {
LifecycleUtils.destroy(getCacheManager());
this.cacheManager = null;
}

}

Realm 管理也是一样的,使用了代理模板~,注入成员函数去处理

public abstract class RealmSecurityManager extends CachingSecurityManager {

// 各种各样的,可以通过Ini配置进行处理哦~,然后获取就可以进行处理了
private Collection<Realm> realms;

public void setRealm(Realm realm) {
if (realm == null) {
throw new IllegalArgumentException("Realm argument cannot be null");
}
Collection<Realm> realms = new ArrayList<Realm>(1);
realms.add(realm);
setRealms(realms);
}

public void setRealms(Collection<Realm> realms) {
if (realms == null) {
throw new IllegalArgumentException("Realms collection argument cannot be null.");
}
if (realms.isEmpty()) {
throw new IllegalArgumentException("Realms collection argument cannot be empty.");
}
this.realms = realms;
afterRealmsSet();
}

protected void afterRealmsSet() {
applyCacheManagerToRealms();
}

public Collection<Realm> getRealms() {
return realms;
}

}

Authenticator 认证信息,代理

public abstract class AuthenticatingSecurityManager extends RealmSecurityManager {

/**
* The internal <code>Authenticator</code>
delegate instance that this SecurityManager instance will use
* to perform all authentication operations.
代理所有的 Authenticator(证明者,认证者;密码证明信号)
*/
private Authenticator authenticator;

/**
* Default no-arg constructor that initializes its internal
* <code>authenticator</code> instance to a
* {@link org.apache.shiro.authc.pam.ModularRealmAuthenticator ModularRealmAuthenticator}.
*/
public AuthenticatingSecurityManager() {
super();
this.authenticator = new ModularRealmAuthenticator();
}

public Authenticator getAuthenticator() {
return authenticator;
}

//设置自定义的验证器,很好的扩展
public void setAuthenticator(Authenticator authenticator)
throws IllegalArgumentException {
if (authenticator == null) {
String msg = "Authenticator argument cannot be null.";
throw new IllegalArgumentException(msg);
}
this.authenticator = authenticator;
}

/**
* Passes on the {@link #getRealms() realms} to
the internal delegate <code>Authenticator</code> instance so
* that it may use them during authentication attempts.
*/
protected void afterRealmsSet() {
super.afterRealmsSet();
if (this.authenticator instanceof ModularRealmAuthenticator) {
((ModularRealmAuthenticator) this.authenticator).setRealms(getRealms());
}
}

/**
* 代理啊!!哈哈
*/
public AuthenticationInfo authenticate(AuthenticationToken token)
throws AuthenticationException {
return this.authenticator.authenticate(token);
}


}

Authrizer:授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能

public abstract class AuthenticatingSecurityManager extends RealmSecurityManager {

/**
* The internal <code>Authenticator</code>
delegate instance that this SecurityManager instance will use
* to perform all authentication operations.
代理信息
*/
private Authenticator authenticator;

public AuthenticatingSecurityManager() {
super();
this.authenticator = new ModularRealmAuthenticator();
}
public Authenticator getAuthenticator() {
return authenticator;
}

/**
设置自定义访问控制器
**/
public void setAuthenticator(Authenticator authenticator) throws IllegalArgumentException {
if (authenticator == null) {
String msg = "Authenticator argument cannot be null.";
throw new IllegalArgumentException(msg);
}
this.authenticator = authenticator;
}
protected void afterRealmsSet() {
super.afterRealmsSet();
if (this.authenticator instanceof ModularRealmAuthenticator) {
((ModularRealmAuthenticator) this.authenticator).setRealms(getRealms());
}
}


public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {
return this.authenticator.authenticate(token);
}

}

session管理,这些代码写的非常的经典啊,格式非常的相同

public abstract class SessionsSecurityManager extends AuthorizingSecurityManager {

/**
* The internal delegate <code>SessionManager</code> used by this security manager that manages all the
* application's {@link Session Session}s.
*/
private SessionManager sessionManager;

/**
* Default no-arg constructor, internally creates a suitable default
{@link SessionManager SessionManager} delegate
* instance.
*/
public SessionsSecurityManager() {
super();
this.sessionManager = new DefaultSessionManager();
applyCacheManagerToSessionManager();
}


public void setSessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
afterSessionManagerSet();
}

protected void afterSessionManagerSet() {
applyCacheManagerToSessionManager();
}

public SessionManager getSessionManager() {
return this.sessionManager;
}

protected void afterCacheManagerSet() {
super.afterCacheManagerSet();
applyCacheManagerToSessionManager();
}

protected void applyCacheManagerToSessionManager() {
if (this.sessionManager instanceof CacheManagerAware) {
((CacheManagerAware) this.sessionManager).setCacheManager(getCacheManager());
}
}
public Session start(SessionContext context) throws AuthorizationException {
return this.sessionManager.start(context);
}
public Session getSession(SessionKey key) throws SessionException {
return this.sessionManager.getSession(key);
}
public void destroy() {
LifecycleUtils.destroy(getSessionManager());
this.sessionManager = null;
super.destroy();
}
}

身份验证还是没有讲…..这个超标了,主要是觉得代码写的非常的好!