Shiro是什么
Apache提供的Java轻量级安全框架, 相比Spring Security更为简单。
作用主要包括: 认证、授权、加密和会话管理。
核心概念:
Subject: 主体
对应应用程序的用户(User),Shiro为了避免冲突,从前安全角度起的名字, 实际就是当前登录的用户。
SecurityManager-安全管理器
用于管理主体以及权限。
Realms:域
充当Shiro与应用程序的安全数据之间的“桥梁”或“连接器”。也就是Shiro会从应用程序中获取身份验证和授权的信息。
简单点说,就是安全数据源。 应用中至少需要配置一个Relam,可以使用多种方式,比如.ini的文件,JDBC数据库连接或是LDAP。
SecurityManager的初始化
在Web应用中,通过在web.xml中配置Shiro的Servlet过滤器;
在独立应用中,可以通过多种配置方式,包括Java代码、Spring XML,YAML、.properties和.ini文件。
以INI配置为例:shiro.ini
[users]
oscar = 123456, admin
[roles]
admin = *
[users] 配置静态的用户列表, 方便测试
[roles] 配置角色和权限
主体、角色和权限
主体分配角色, 角色分配权限
比如:主体:root, 角色:admin, 权限: *
root用户拥有admin角色,admin角色拥有所有权限。
在老版本中, SecurityManager通过工厂类的方式初始化,但是现在这种方式已经废弃了, 不建议使用。
Factory factory = new IniSecurityManagerFactory(“classpath:shiro.ini”);
SecurityManager securityManager = factory.getInstance();
新版本 SecurityManager初始化方法
DefaultSecurityManager securityManager = new DefaultSecurityManager();
IniRealm iniRealm = new IniRealm(“classpath:shiro.ini”);
securityManager.setRealm(iniRealm);
用户认证(Authentication)
用户认证是认证该用户是否是应用的合法用户。
认证步骤:
- 收集用认证的身份信息, 以用户名密码登录为例,产生的认证Token如下:
AuthenticationToken token = new UsernamePasswordToken(“oscar”, “123456”);
-
获取当前主体
Subject currentUser = SecurityUtils.getSubject(); -
使用产生的Token登录
currentUser.login(token);
该方法可以通过异常捕获获取异常信息,比如密码错误等。
授权(Authorization)
认证后的用户是否对应用的资源、页面等有权限访问。Shiro主要通过角色(Role)和权限(Permission)实现。
授权可以判断该用户是否具有某个角色,或是该主体对某个类或是实例是否有权限操作, 代码示例如下:
//4.1 是admin角色
if(currentUser.hasRole("admin")) {
}
//4.2 有创建用户权限(类层级)
if (currentUser.isPermitted("user:create") ) {
}
//4.3 有删除oscar这个用户的权限(实例层级)
if (currentUser.isPermitted("user:delete:oscar") ) {
}
public class ShiroDemo {
public static void main(String[] args) {
//1. 初始化安全管理器SecurityManager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
securityManager.setRealm(iniRealm);
SecurityUtils.setSecurityManager(securityManager);
//2. 获取主体
Subject currentUser = SecurityUtils.getSubject();
//3.用户名/密码验证
if (!currentUser.isAuthenticated()) {
System.out.println("开始验证");
UsernamePasswordToken token = new UsernamePasswordToken("oscar", "123456");
token.setRememberMe(true);
try {
currentUser.login(token);
} catch (UnknownAccountException uae) {
System.out.println("用户不存在:" + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
System.out.println("密码错误: " + token.getPrincipal() + " ");
} catch (LockedAccountException lae) {
System.out.println("账号被锁了");
}
System.out.println("验证成功");
}
//4. 授权判断
//4.1 是admin角色
if(currentUser.hasRole("admin")) {
}
//4.2 有创建用户权限(类层级)
if (currentUser.isPermitted("user:create") ) {
}
//4.3 有删除oscar这个用户的权限(实例层级)
if (currentUser.isPermitted("user:delete:oscar") ) {
}
//5.登出
currentUser.logout();
}
}