Shiro_02_基础概念
something before start
shiro有很多的概念命名其实是面向安全框架领域的,有一些和我们日常生活中的常用词不太一样,不过好在都很容易找到相近含义的词汇。
入门过程最好是配合代码一起学习,这是我的Shiro学习Demo仓库,非常建议开始看博客前先把代码运行起来。
基础概念
Subject
Subject
:用户的安全视图(a security-specific “view” of an application User.),可以简单理解为User
、当前与应用交互的对象。
// 获得当前用户
Subject currentUser = SecurityUtils.getSubject();
使用SecurityUtils.getSubject()
即可获取当前的Subject
在单机环境下,Subject基于应用中的用户数据
在Web环境下,Subject基于请求(request)或者当前的线程
session
Session
:类似于HttpSession,但是shiro的会话不依赖于HTTP环境
// 获取当前的session
Session session = currentUser.getSession();
session.setAttribute("someKey", "aValue");
String value = (String) session.getAttribute("someKey");
if (value.equals("aValue")) {
log.info("Retrieved the correct value! [" + value + "]");
}
获取了当前用户之后,就可以得到当前用户的会话(session)并进行读写操作。
在non-Web环境下,shiro默认会使用它的企业级Session管理器(Enterprise Session Management)
在Web环境下,shiro的session则基于HttpSession
认证
认证
:明确用户的身份,从用户的角度来讲叫做登陆
得到当前的Subject(用户)之后,我们就可以对其进行身份认证。
下面介绍两个关于身份认证的概念 token
和realm
token
token
:令牌,一般我们常见的username-password
就是一种令牌。shiro中有自带了几种默认令牌,如果有需要的话我们可以通过实现AuthenticationToken
接口来自定义令牌。
UsernamePasswordToken token = new UsernamePasswordToken("guest", "guest");
realm
realm
:用于存储关于用户的安全数据的组件。同时也是对token进行校验的地方
shiro通过realm来获取用户的安全信息,比如账号密码,用户的身份(role),可以进行的操作(pemission)。
realm可以和数据库、系统文件等进行交互,它使得shiro和底层数据存储耦合度降低,可以根据用户的需求来选择安全数据存储在什么地方。
在本项目中,使用了shiro.ini
文件来配置realm。//该方法简单看看明白大概是什么意思就行,没必要深究
# 配置用户的账号密码
[users]
# 用户 root 密码为secret,角色为admin
root = secret, admin
guest = guest, guest
# 用户 lonestarr 密码为vespa,角色为goodguy和schwartz
lonestarr = vespa, goodguy, schwartz
# role设置,左边是role,右边是permission
# permission有规范的语法,详情看后面的博客,这里暂时只做简单的理解
# ‘:’为层级分隔符,‘*’为通配符
[roles]
# 'admin' role(身份) 有所有种类的 permissions(操作权限),*为通配符
admin = *
# The 'schwartz' role 可以做任何以 lightsaber: 开头的权限
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5
一些关于认证的操作
currentUser.isAuthenticated()
:判断当前用户是否已经被授权
currentUser.login(token);
:根据token进行登陆.
如果校验通过,则当前用户状态变更为已认证,isAuthenticated()
返回true
如果校验失败,则抛出异常
// 登陆测试
if (!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken("guest", "guest");
// UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
token.setRememberMe(true);
try {
currentUser.login(token);
} catch (UnknownAccountException uae) {
log.info("There is no user with username of " + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
log.info("Password for account " + token.getPrincipal() + " was incorrect!");
} catch (LockedAccountException lae) {
log.info("The account for username " + token.getPrincipal() + " is locked. " +
"Please contact your administrator to unlock it.");
}
// ... catch more exceptions here (maybe custom ones specific to your application?
catch (AuthenticationException ae) {
//unexpected condition? error?
}
}
logout
currentUser.logout();
:会把这次会话中的临时信息删除干净,比如session。然后清除当前用户的认证状态
授权
授权
:让特定的用户进行某种操作.
role
role
:角色,常见的role有admin
、guest
等
permission
permission
:操作权限,一般以操作命名。常见操作权限即增删改查权限。
支持不同的层级,以:
作为分割。支持通配符*
举几个例子来做简单理解:
book:query``book:add``book:delete
:对书进行搜索、增加、查询操作
book:*
:对书本可以有任何的操作
*:add
:对任何主体都可以进行增加操作
book:add:store1
:对store1仓库的书进行增加
book:*:store1
:对store1仓库的书进行任何的操作
另外,末尾的*
可以缺省
如:book
等价于 book:*:*
因为它的permission校验不是简单的字符串比对,它会根据一定的格式对字符串进行拆分之后在进行对比,后面的博客会简单看看他的对比逻辑
一些关于授权的操作
currentUser.hasRole("schwartz")
currentUser.isPermitted("lightsaber:wield")
SecurityManager
shiro的核心部件,将各个组件组合到一起,然后将对应的接口提供给Subject
其他一些组件
因为涉及到一些源码流程的内容,这里只是简单提及。
Authenticator
认证器
Authorizer
授权器
Authentication Strategy
授权策略
SessionManager
session管理器
SessionDAO
session数据存取器
CacheManager
缓存管理器
Cryptography
密码器