官网:shiro
先看看从官网偷来的图
shiro的三个主要组件:Subject、SecurityManager、Realm
Subject
:我们可以将它看作是当前用户或第三方服务,
SecurityManager
:管理所有的Subject
,是Shiro
的核心组件
Realm
:获取用户的认证数据
接下来通过代码来认识下这几个组件
添加maven
依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
首先我们利用SimpleAccountRealm
来组织服务端的安全数据,利用UsernamePasswordToke
来组织外部待认证的数据
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
simpleAccountRealm.addAccount("baidu", "guest");
UsernamePasswordToken token = new UsernamePasswordToken("baidu", "guest");
接下来创建shiro
的核心组件SecurityManager
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
将之前创建的simpleAccountRealm
交由defaultSecurityManager
管理
defaultSecurityManager.setRealm(simpleAccountRealm);
Shiro
提供了一个抽象的工具类SecurityUtils
来保存创建的SecurityManager
对象并获取Subject
对象
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
上面两行代码顺序不可乱
查看SecurityUtils.getSubject()
方法的代码,其内部使用的是Subject
接口的内部类Builder
创建Subject
对象,而Builder
实例化时使用了SecurityManager
作为参数
public static class Builder {
private final SubjectContext subjectContext;
private final SecurityManager securityManager;
public Builder() {
this(SecurityUtils.getSecurityManager());
}
public Builder(SecurityManager securityManager) {
if (securityManager == null) {
throw new NullPointerException("SecurityManager method argument cannot be null.");
}
this.securityManager = securityManager;
this.subjectContext = newSubjectContextInstance();
if (this.subjectContext == null) {
throw new IllegalStateException("Subject instance returned from 'newSubjectContextInstance' " +
"cannot be null.");
}
this.subjectContext.setSecurityManager(securityManager);
}
}
SecurityUtils中的getSecurityManager()的部分代码如下:
SecurityManager securityManager = ThreadContext.getSecurityManager();
if (securityManager == null) {
securityManager = SecurityUtils.securityManager;
}
当从当前线程中获取不到SecurityManager
时取的便是之前我们设置到SecurityUtils
中的SecurityManager
对象
到此,前面图中提到的三个组件均已创建,那么我们该做认证了!
subject.login(token);
使用断言判断我们认证是否成功
Assert.assertEquals(true, subject.isAuthenticated());
修改UsernamePasswordToke
实例时的参数,重新运行程序观看结果
UsernamePasswordToken token = new UsernamePasswordToken("Tencent", "guest");
完整代码如下:
@Test
public void helloShiro() {
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
simpleAccountRealm.addAccount("baidu", "guest");
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("baidu", "guest");
subject.login(token);
Assert.assertEquals(true, subject.isAuthenticated());
}