shiro笔记
作者:互联网
shiro笔记
shiro简述
- Apache Shiro 是java的一个安全框架
- Shiro 可以做:认证、授权、加密、会话管理、Web集成、缓存等功能。
- 官网:http://shiro.apache.org/
功能介绍
- Authentication:身份认证/登录,验证用户是不是拥有相应的身份
- Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;
- Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境,也可以是 Web 环境的;
- Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
- Web Support:Web 支持,可以非常容易的集成到Web 环境;
- Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
- Concurrency:Shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
- Testing: 提供 测试 支持
- Run As: 允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
- Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了
Shiro与Spring Security对比
共同点: 认证、授权、加密、会话、缓存、remember Me功能...
不同点: Shiro配置和使用比较简单,Spring Sccurity上手复杂.Shiro依赖性低,不需要任何框架和容器,可以独立运行,而Spring Security依赖于Spring容器.
Shiro四大核心功能
Authentication
- 身份认证:
一般用于登录:登陆时,验证用户是否拥有相应身份。
Authorization
- 访问控制:
验证已认证用户是否拥有某些权限,可以让他进行权限内的操作。
Cryptography
- 密码加密:
将密码加密储存到数据库,而不是明文储存,可以保护数据的安全性。
Session Management
- 会话管理:
用户登录后就是第一次会话,在会话结束(退出登录)前,他所有的信息都在会话中。
Shiro三个核心组件
Subject-主体:
应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心是Subject。
Subject的所有交互都会委托给SecurityManager(实际的执行者)。
SecurityManager-安全管理器:
SecurityManager是Shiro的核心,负责与Shiro的其他组件进行交互,相当于SpringMVC中DispatcherServlet的角色。
它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理,所有具体的交互都通过SecurityManager 进行控制。
SecurityManager是一个单例对象,一个应用中只需要一个SecurityManager.
Realm-域
Shiro从Realm获取安全数据(如用户、角色、权限),
就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;
也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;
可以把Realm看成DataSource,即安全数据源。
shiro中的认证
身份认证,就是判断一个用户是否为合法用户的处理过程。最常见的简单身份验证方式是通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。
shiro中认证的关键对象
- Subject:主体
访问系统的用户,主体可以是用户、程序等。 - Principal:身份信息
是主体进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等。一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。 - credential:凭证信息
是只有主体自己知道的安全信息,如密码、证书等。
认证流程
认证的开发
- 创建Spring Boot项目
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.5.3</version>
</dependency>
- 引入shiro配置文件
配置文件:名称随意,以 .ini结尾,放在resources目录下。
注意:在实际的项目开发中并不会使用这种方式,这种方法可以用来初学时练手!
[users]
king=123456
wang=123456
- 开发认证代码
public class ShiroDemo{
public static void main(String[] args){
//1.创建安全管理器对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2.给安全管理器设置realm
securityManager.setRealm(new InitRealm("classpath:shiro.ini"));
//3.SecurityUtils全局安全工具类设置安全管理器
SecurityUtils.setSecurityManager(securityManager);
//4.关键对象subject主体
Subject subject = SecurityUtils.getSubject();
//5.创建令牌
UsernamePasswordToken token = new UsernamePasswordToken("king","123456");
try{
System.out.println("认证状态"+subject.isAuthenticated());//fasle
//用户认证
subject.login(token);
System.out.println("认证状态"+subject.isAuthenticated());
}catch(UnknownAccountException e){
e.printStackTrace();
System.out.println("认证失败,用户名不存在");
}catch(IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("认证失败,密码错误");
}
}
}
- 常见的异常类型
- DisabledAccountException(帐号被禁用)
- LockedAccountException(帐号被锁定)
- ExcessiveAttemptsException(登录失败次数过多)
- ExpiredCredentialsException(凭证过期)等
自定义Realm
通过分析源码可得,
- 最终执行用户名比较的的是 在SimpleAccountRealm类 的doGetAuthenticationInfo 方法完成用户名校验。
- 最终密码校验是在 AuthenticatingRealm类 的 assertCredentialsMatch方法 中。
shiro提供的Realm
根据认证源码认证使用的是SimpleAccountRealm
public class SimpleAccountRealm extends AuthorizingRealm{
//......省略
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
SimpleAccount account = getUser(upToken.getUsername());
if (account != null) {
if (account.isLocked()) {
throw new LockedAccountException("Account [" + account + "] is locked.");
}
if (account.isCredentialsExpired()) {
String msg = "The credentials for account [" + account + "] are expired";
throw new ExpiredCredentialsException(msg);
}
}
return account;
}
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = getUsername(principals);
USERS_LOCK.readLock().lock();
try {
return this.users.get(username);
} finally {
USERS_LOCK.readLock().unlock();
}
}
}
接下里,开始自定义realm!
/**
* 自定义Realm
*/
public class CustomerRealm extends AuthorizingRealm{
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("==================");
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//在token中获取 用户名
String principal = (String) token.getPrincipal();
System.out.println(principal);
//实际开发中应当 根据身份信息使用jdbc mybatis查询相关数据库
//在这里只做简单的演示
//假设username,password是从数据库获得的信息
String username="zhangsan";
String password="123456";
if(username.equals(principal)){
//参数1:返回数据库中正确的用户名
//参数2:返回数据库中正确密码
//参数3:提供当前realm的名字 this.getName();
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal,password,this.getName());
return simpleAuthenticationInfo;
}
return null;
}
}
标签:account,Realm,用户,笔记,认证,shiro,Shiro 来源: https://www.cnblogs.com/zhangy0119/p/16119706.html