认证
身份认证:判断一个用户是否为一个合法用户的过程。
认证方式:用户名口令认证、短信验证码、第三方授权。
认证需要的关键对象:
- Subject:主体,访问系统的用户,主体可以是用户、程序等
- Principal:身份信息是主体进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址。一个主题可以有多个身份,但必须有一个主身份(Primary Principal)
- credential:凭证信息,只有主体自己知道的安全信息,如密码、证书
授权
授权:访问控制,控制谁能访问哪些资源。主体进行身份认证后,系统会为其分配对应的权限,当访问资源时,会校验其是否有此权限。
授权需要操作的对象:
- 用户对象user:当前操作的用户、程序
- 资源对象Resource:被访问的资源
- 角色对象role:一组"权限操作许可权"的集合
- 权限对象permission:权限操作许可权
什么是Shiro
Shiro是一个开源的安全认证框架。实现用户身份认证、权限授权、加密、会话管理等功能。
核心组件
subject
外部程序与subject进行交互,而Subject通过SecurityManager安全管理进行认证授权。
外部程序----------subject---------SecurityManager
SecurityManager(权限管理器)
它是Shiro的核心,对所有subject进行管理。通过SecurityManager完成subject的认证、授权。SecurityManager是通过Authenticator进行认证;通过Authorizer进行授权;通过SessionManager进行会话管理。SecurityManager是一个接口,继承Authenticator、Authorizer、SessionManager这三个接口。
Authenticator(认证器)
对用户登录进行身份认证
Authorizer(授权器)
认证通过后,在访问功能时通过Authorizer判断用户是否有操作权限
Realm(数据库读取+认证功能+授权功能实现)
Realm相当于DataSource数据源。SecurityManager进行安全认证需要通过Realm获取用户权限数据。
比如:用户身份数据在数据库,那么realm需要从数据库获取身份信息。
注意:realm除了从数据源获取身份信息,在realm中还有认证授权校验的相关代码。
SessionManager(会话管理)
Shiro框架定义的一套会话管理系统,它不依赖Web容器的Session,所以Shiro可以用在非Web应用上,也可以将分布式应用的会话集中在一点管理,此特性可使它实现单点登录。
SessionDAO(会话DAO)
可通过jdbc将会话存储到数据库,也可以把 Session存储到缓存服务器。
CacheManager(缓存管理)
将用户权限数据存储在缓存,可以提高性能。
Cryptography(密码管理)
Shiro提供的一套加密/解密组件,比如提供常用的散列、加/解密功能。
Shiro入门
身份认证
认证流程:
- Shiro把用户的数据封装成标识token,token封装了用户名、密码等信息
- subject获取到这个标识token
- subject把标识token交给SecurityManager,在SecurityManager安全中心中,SecurityManager把标识token交给认证器Authenticator进行身份认证。
- 认证器Authenticator将标识token与数据源Realm对比,验证token是否合法。
代码示例
导入依赖
xml
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 这里有用到日志打印,所以引入 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
构造shiro.ini文件
java
# -----------------------------------------------------------------------------
# users用来定义用户
[users]
# 用户名 = 密码,角色1,角色2...
admin = secret, admin
guest = guest, guest
aa = 123456, guest
# -----------------------------------------------------------------------------
# roles用来定义角色
[roles]
# 角色 = 权限 (* 代表所有权限)
admin = *
# 角色 = 权限 (* 代表所有权限)
guest = see
aa = see
示例代码
java
package demo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ShiroDemo {
private static final Logger log = LoggerFactory.getLogger(ShiroDemo.class);
public static void main(String[] args) {
//1.导入权限ini文件,创建SecurityManagerFactory
IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//2.获取SecurityManager,绑定到SecurityUtils中
SecurityManager securityManager =factory.getInstance();
SecurityUtils.setSecurityManager( securityManager);
//3.获取一个用户主体
Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("guest", "guest");
currentUser.login(token);
System.out.println("是否登录成功:"+currentUser.isAuthenticated());
}
}