> 戒色诗: 二八佳人体似酥,腰间仗剑斩凡夫。虽然不见人头落,暗里教君骨髓枯。
关于Shiro 的教程,推荐大家看 张开涛前辈写得 跟我学Shiro, 写得非常好。
老蝴蝶写得这个 Shiro 系列,侧重于实际应用,所以太深奥的内容不进行讲解,大家看张开涛前辈写的Shiro 文章就好。
另,本系列shiro 内容会大量参考张开涛前辈的文章,谢谢!!!
一. Shiro的出现
一.一 为什么要出现 Shiro?
前面,我们在控制权限,保障数据隐私和安全时,都是自己编写的代码程序进行相应的控制。
我们自己前面实现的 权限验证,操作复杂,功能简单,复用率低, 一些常见的功能,如 单点登录,记住我,密码加密等,很难实现,还需要根据不同的框架写不同的过滤器或者拦截器,自己手动配置静态的和不需要认证的页面url.
我们希望能有一个工具,就像 Quartz 实现作业调度一样,实现权限的控制? 我们只需要把用户,角色,权限的数据交给这个工具,通过简单的配置,这个工具就能自动帮我们实现认证和授权的操作。
有这个工具,这个工具就是 Shiro.
Shiro 可以帮我们快速地实现 认证和授权的功能,保障系统地安全。
一.二 Shiro的简介和下载
Shiro 是一个强大的 Java安全框架,越来越多的人使用它。适用于 JavaSE 和 JavaEE。
可以进行 认证,授权,加密和会话管理 ,也支持Web,单点登录,记住我等功能。
Shiro属于Apache 组织下的项目,官网为: http://shiro.apache.org/
我们下载的是经典的 1.2.2 版本
在maven 中直接 引入 shiro-all 的依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.2</version>
</dependency>
相应的jar包为:
在写 shiro 的例子之前,我们需要先了解关于Shiro 的一些概念。(概念摘录于张开涛前辈的shiro文章)
二. Shiro 相关概念介绍
二.一 Shiro 的功能模块
二.一.一 功能模块图片
Shiro 会我们提供了这些功能。
二.一.二 功能模块解释
功能模块名对应解释
Authentication身份认证(通俗讲为登录),验证用户是否是合法的用户
Authorization授权(通俗讲为权限验证),验证某个已经认证通过的用户是否具有某个权限,用于判断用户是否能做某些事情
Session Manager会话管理。用户登录后就是一次会话,在没有退出之前,它的所有的信息都会在会话里面。会话可以是 JavaSE环境,也可以是Web环境
Cryptography加密,用于保护数据的安全性,如密码加密,而不是明文存储
Web SupportWeb支持,用于集成到 Web环境
Caching缓存,用户登录之后,其用户信息,拥有的角色和权限不必每次都去查,可以提高效率,如ehcache缓存
Concurrency多线程并发验证,即如在一个线程中开启另一个线程,就能把权限自动传播过去
Testing提供测试支持
Run As允许一个用户假装为另一个用户(如果他们允许)的身份进行访问
Remember Me记住我,即一次登录后,下次再来的话,就不用重新登录
常用的就是,身份认证 Authentication,授权 Authorization,加密 Cryptography和 记住我 Remember Me.
二.二 Shiro 的外部架构
二.二.一 外部架构图片
Shiro 的三大主体, Subject, SecurityManager, Realm 如何进行工作的。
二.二.二 外部架构的名词解释
名称对应解释
Subject主体,代表当前的"用户",但这个用户不一定指具体的人。
SecurityManager安全管理器,即所有与安全有关的操作都会与Security Manager 进行交互,它管理着所有的 Subject,是 Shiro的核心,负责与Realm 进行交互
Realm域,Shiro从域中获取安全数据,相当于DataSource 数据源
补充: 我们编写的代码里面使用的是 Subject,即应用代码直接交互的对象是 Subject. 所有的Subject 都会绑定到 SecurityManager上,所有的交互也都会委托给SecurityManager, 是一个门面,而Security Manager是实际的执行者。
Security Manager 相当于 SpringMVC的 DispatcherServlet 前端控制器,无处不在,功能强大。
Realm相当于数据源, SecurityManager要验证用户的身份,获取用户的权限,这个数据从哪儿获取呢? 就是通过Realm 进行获取。
总结: 应用代码通过 Subject对象调用方法, 来进行认证和授权,而Subject 又委托SecurityManager处理(即真正干活的是 SecurityManager)需要给SecurityManager 注入Realm, 从而让SecurityManager得到合法的用户信息和角色/权限数据。
注意,数据是我们开发者提供的,Shiro 不维护数据,只查询,不更新。
二.三 Shiro 的内部架构
二.三.一 Shiro 的内部架构图片
具体的功能组件
二.三.二 内部架构解释
名称解释
Subject主体,可以看到主体是任何可以与应用交互的用户
SecurityManager所有具体的交互都是通过它进行控制的,管理着所有的Subject
Authenticator认证器,负责主体认证的,需要配置认证策略 Strategy
Authrizer授权器,用来决定主体是否有权限进行相应的操作
Realm安全实体数据源,用于获取数据
SessionManager会话管理,用于管理Session
SessionDAO用于会话的CRUD
CacheManager缓存管理,用于提高访问的性能,常存储用户,角色,权限
Cryptography密码模块,用于加密用户的密码等隐私数据
二.四 身份认证
身份认证,是在应用中谁能证明他就是他本人。一般提供身份的ID等标识信息来表明他就是他本人,如身份证,用户名/密码等。
包括两个部分,一个 principals(身份),credentials(证明) 两个部分。
二.四.一 principals 身份
即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。一个主体可以有多个principals,但只有一个Primary principals,一般是用户名/密码/手机号。
二.四.二 credentials 证明
即只有主体知道的安全值,如密码/数字证书等
最常见的身份认证就是 用户名和密码。
其中,身份 principals 是用户名,唯一的,
证明 credentials 是密码,只有当前身份的那个用户才知道的凭证。
三. Shiro 进行认证实例
编写一个小的 Demo,来演示一下 Shiro 的具体使用。
三.一 添加 Shiro 的依赖
在 pom.xml 文件中,添加shiro 和junit 测试的 依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yjl.shiro</groupId>
<artifactId>Shiro_Ini</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 编译的jdk版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
三.二 创建配置文件 shiro.ini
用户的身份密码,角色权限等信息,可以暂时配置在 .ini 文件里面。
Shiro 支持从 .ini 配置文件里面读取数据, 但要保证文件的格式正确。
我们往里面添加两个用户, yuejl 和yuezl 两个用户,密码均为 1234.
# 配置用户的信息
[users]
#用户名=密码
yuejl=1234
yuezl=1234
shiro.ini 文件要放置在 classpath 目录下。
三.三 编写 测试Demo
package com.yjl.demo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
/**
*
* @author 两个蝴蝶飞
* Shiro 的第一个演示文件
*/
public class ShiroDemo1 {
public static void main(String[] args) {
//1. 创建工厂
Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro.ini");
//2. 从工厂里面获取 SecurityManager
SecurityManager securityManager=factory.getInstance();
//3. 通过工具类设置 securityManager
SecurityUtils.setSecurityManager(securityManager);
//4. 获取当前登录的用户
Subject subject=SecurityUtils.getSubject();
//5. 拼装用户的身份和密码Token
UsernamePasswordToken token=new UsernamePasswordToken("yuezl","1234"); //1.正确密码
//UsernamePasswordToken token=new UsernamePasswordToken("yuezl","123456"); //2.错误密码
//6. 调用 subject 里面的login 方法,进行登录
try{
subject.login(token);
//7.判断用户是否登录成功
if(subject.isAuthenticated()){
System.out.println("用户:"+token.getUsername()+", 登录成功");
}
}catch(Exception e){
System.out.println("用户登录失败");
}
}
}
正确的密码 1234,进行测试
错误的密码 123456,进行测试
其中, token 对象里面传入的用户名和密码,就是我们以后在前端用户输入的用户名和密码,
shiro.ini 里面的用户名和密码,就是我们从数据库里面读取出来的用户的用户名和密码。
两者是如何进行比较的呢? 是通过 subject.login() 方法进行比较的。
本章节代码链接为:
链接:https://pan.baidu.com/s/1FI_r9DfOhrK84k9ru0zerA
提取码:6z3o
谢谢您的观看,我是两个蝴蝶飞, 如果喜欢,请关注我,再次感谢 !!!