一、
1.Subject 是与程序进行交互的对象,可以是人也可以是服务或者其他,通常就理解为用户。所有Subject 实例都必须绑定到一个SecurityManager上。我们与一个 Subject 交互,运行时shiro会自动转化为与 SecurityManager交互的特定 subject的交互。
2.SecurityManager 是 Shiro的核心,初始化时协调各个模块运行。然而,一旦 SecurityManager协调完毕,SecurityManager 会被单独留下,且我们只需要去操作Subject即可,无需操作SecurityManager 。 但是我们得知道,当我们正与一个 Subject 进行交互时,实质上是 SecurityManager在处理 Subject 安全操作.
3.Realms在 Shiro中作为应用程序和安全数据之间的“桥梁”或“连接器”。他获取安全数据来判断subject是否能够登录,subject拥有什么权限。他有点类似DAO。在配置realms时,需要至少一个realm。而且Shiro提供了一些常用的 Realms来连接数据源,如LDAP数据源的JndiLdapRealm,JDBC数据源的JdbcRealm,ini文件数据源的IniRealm,properties文件数据源的PropertiesRealm,等等。我们也可以插入自己的 Realm实现来代表自定义的数据源。 像其他组件一样,Realms也是由SecurityManager控制.
二、
-
Subject(org.apache.shiro.subject.Subject):
简称用户 -
SecurityManager(org.apache.shiro.mgt.SecurityManager)
如上所述,SecurityManager是shiro的核心,协调shiro的各个组件 -
Authenticator(org.apache.shiro.authc.Authenticator): Authentication Strategy
(org.apache.shiro.authc.pam.AuthenticationStrategy)
登录控制
①、如果存在多个realm,则接口AuthenticationStrategy会确定什么样算是登录成功(例如,如果一个Realm成功,而其他的均失败,是否登录成功?。答:①SecurityManager接口继承了Authenticator,另外还有一个ModularRealmAuthenticator实现,其委托给多个Realm进行验证,验证规则通过AuthenticationStrategy接口指定,默认提供的实现:
②.FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略;
③.AtLeastOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,返回所有Realm身份验证成功的认证信息;
④.AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。 -
Authorizer(org.apache.shiro.authz.Authorizer) :
决定subject能拥有什么样角色或者权限 -
SessionManager(org.apache.shiro.session.SessionManager) :
创建和管理用户session。通过设置这个管理器,shiro可以在任何环境下使用session -
CacheManager(org.apahce.shiro.cache.CacheManager) :
缓存管理器,可以减少不必要的后台访问。提高应用效率,增加用户体验。 -
Cryptography(org.apache.shiro.crypto.*) :
Shiro的api大幅度简化java api中繁琐的密码加密。 -
Realms(org.apache.shiro.realm.Realm) :
程序与安全数据的桥梁 -
Spring security 与apache shiro 差别:
shiro配置更加容易理解,容易上手;security配置相对比较难懂。
在spring的环境下,security整合性更好。Shiro对很多其他的框架兼容性更好,号称是无缝集成。
shiro 不仅仅可以使用在web中,它可以工作在任何应用环境中。
在集群会话时Shiro最重要的一个好处或许就是它的会话是独立于容器的。
Shiro提供的密码加密使用起来非常方便
三、 -
shiro 的 认证过程
public class DemoApplicationTests {
SimpleAccountRealm accountRealm = new SimpleAccountRealm();
@Before
public void addUser(){
accountRealm.addAccount("nigl","123456");
}
@Test
public void testAuthticator(){
//构建环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(accountRealm);
//提交主体认证
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject =SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("nigl","123456");
//登录
subject.login(token);
System.out.println("isAuthenticatedss:"+subject.isAuthenticated());
//退出
subject.logout();
System.out.println("isAuthenticated:"+subject.isAuthenticated());
}
}
- shiro 授权过程
首先构建环境,提交主体授权–> securityManager授权–>authorizer授权(授权器)–>Realm获取角色权限数据
public class DemoApplicationTests {
SimpleAccountRealm accountRealm = new SimpleAccountRealm();
@Before
public void addUser(){
//添加账户 和 角色权限
accountRealm.addAccount("nigl","123456");
}
@Test
public void testAuthticator(){
//构建环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(accountRealm);
//提交主体认证
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject =SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("nigl","123456","admin","user");
//登录
subject.login(token);
System.out.println("isAuthenticatedss:"+subject.isAuthenticated());
try {
subject.checkRole("admin","user");
}catch (Exception e){
e.printStackTrace();
//会提示:org.apache.shiro.authz.UnauthorizedException: Subject does not have role [admin]
}
}
}
- shiro 的Realm,内置的Realm 有 IniRealm 和 JdbcRealm;
public class IniRealmTest {
@Test
public void testAuthticator(){
//构建环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
IniRealm iniRealm = new IniRealm("classpath:user.ini");
defaultSecurityManager.setRealm(iniRealm);
//提交主体认证
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject =SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("nigl","123456");
//登录
subject.login(token);
System.out.println("isAuthenticatedss:"+subject.isAuthenticated());
try {
subject.checkRoles("admin");
subject.checkPermissions("user:delete");
}catch (Exception e){
e.printStackTrace();
如果无权限: Subject does not have permission [user:delete1]
}
}
}
user.ini 的配置文件内容
[users]
nigl=123456,admin
[roles]
admin=user:delete,user:add
四、
- shiro 过滤器
内置的有
认证相关:anon(不需要认证),authc(需要认证后才可以访问),authBasic(http 认证),logout(退出),user(当前存在用户才可以访问)
授权相关:perms[],roles[] (指定需要授权的角色),ssl,port(授权的端口)
shiro 自定义过滤器
五、 - 会话管理 -->shiro Session 管理
用户登录之后,3分钟之内可自动登录,之后需要重新登陆,下面是设置session的过期时间代码
@RequestMapping("/loginUser")
public String loginUser(@RequestParam("username") String username,
@RequestParam("password") String password) {
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
//import org.apache.shiro.session.Session;
Session session=subject.getSession();
//设置session 过期时间 为 180000ms == 3 分钟
session.setTimeout(180000);
try {
System.out.println("获取到信息,开始验证!!");
subject.login(token);//登陆成功的话,放到session中
User user = (User) subject.getPrincipal();
session.setAttribute("user", user);
return "redirect:index";
} catch (Exception e) {
e.printStackTrace();
return "redirect:login";
}
}
SessionManager管理 以及 sessionDao
redis 实现共享==> 重写其增删改查等一些方法
demo 地址:https://download.csdn.net/download/lining_s/10899671
源码:https://github.com/ningL32/springbootShiro