01_Shiro是什么
- Shiro一个授权和认证的这样一个框架
- Shiro可以进行认证、授权、Cache的管理、Session的管理、RememberMe功能的实现、加密、退出等 …
其他常见安全拦截框架:Spring Security,OAuth2.0 协议等…
02_Shiro的核心组件
Shiro 三大核心组件: Subject、Security Manager、Realms
- Subject 表示待认证和授权的用户
- Principal:用户名(还可以是用户信息的封装)
- Credential:密码
- Token:令牌(用户名+密码的封装)----进行进行认证的封装对象,这个的对象并不是前后分离的这个token
- Security Manager :它是Shiro框架的核心,Shiro就是通过Security Manager来进行内部实例的管理,并通过它来提供安全管理的各种服务
- Authenticator:认证器
- Anthorizer:授权器
- SessionManager:会话管理器
- CacheManager:缓存管理器
- Realm :相当于Shiro进行认证和授权的数据源,充当了Shiro与安全数据之间的“桥梁”或者“连接器”。也就是说,当对用户进行认证(登录)和授权(访问控制)验证时,Shiro会用应用配置的Realm中查找用户及其权限信息
03_Shiro的核心功能
- Anthentication 认证,验证用户是否有相应的身份—登录认证;
- Authorization 授权,即权限验证;对已经通过认证的用户检查是否具有某个权限或者角色,从而控制是否能够进行某种操作;
- Session Managment 会话管理,用户在认证成功之后创建会话,在没有退出之前,当前用户的所有信息都会保存在这个会话中;可以是普通的JavaSE应用,也可以是web应用;
- Cryptography 加密,对敏感信息进行加密处理,shiro就提供这种加密机制;
支持的特性:
- Web Support —— Shiro提供了过滤器,可以通过过滤器拦截web请求来处理web应用的访问控制
- Caching —— Shiro可以缓存用户信息以及用户的角色权限信息,可以提高执行效率
- Concurrency —— Shiro支持多线程应用
- Testing —— 提供测试支持
- Run As —— 允许一个用户以另一种身份去访问
- Remeber Me —— 提供记住我权限级别
Shiro是一个安全框架,不提供用户、权限的维护(用户的权限管理需要自己去设计)
04_Shiro的基本使用
//1.创建安全管理器
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2.创建realm
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
//3.将realm设置给安全管理器
securityManager.setRealm(iniRealm);
//4.将Realm设置给SecurityUtils工具
SecurityUtils.setSecurityManager(securityManager);
//5.通过SecurityUtils工具类获取subject对象
Subject subject = SecurityUtils.getSubject();
/*
*认证流程
**/
//a.将认证帐号和密码封装到token对象中
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
//b.通过subject对象调用login方法进行认证申请:
boolean b = false;
try{
subject.login(token);
b = true;
}catch(IncorrectCredentialsException e){
b = false;
}
System.out.println(b?"登录成功":"登录失败");
/*
*授权
**/
//判断是否有某个角色
subject.hasRole("seller");
//判断是否有某个权限
subject.isPermitted("order-del");
05_Shiro的自定义Realm
/**
* 1.创建一个类继承AuthorizingRealm类(实现了Realm接口的类)
* 2.重写doGetAuthorizationInfo和doGetAuthenticationInfo方法
* 3.重写getName方法返回当前realm的一个自定义名称
*/
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserDao userDao;
@Override
public String getName() {
return "myRealm";
}
/**
* 获取授权数据:权限角色管理
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取用户的用户名
Object username = principalCollection.getPrimaryPrincipal();
//根据用户名查询当前用户的角色列表
List<String> permissionList = userDao.findPermission(username.toString());
//根据用户名查询当前用户的权限列表
List<String> findList = userDao.findRole(username.toString());
//将权限集合交给Shiro
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addStringPermissions(permissionList);
simpleAuthorizationInfo.addRoles(findList);
return simpleAuthorizationInfo;
}
/**
* 获取认证的安全数据:登录
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//参数authenticationToken就是传递的 subject.login(token)
// 从token中获取用户名
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
String username = usernamePasswordToken.getUsername();
//根据用户名,从数据库查询当前用户的安全数据
UserInfo userInfo = userDao.findUserInfoByAccount(username);
/**
* 参数1:当前用户用户名
* 参数2:从数据库查询出来的安全密码
* 参数3:realm的唯一名称
*/
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userInfo.getAccount(),userInfo.getPassword(),getName());
//将simpleAuthenticationInfo交给SecurityManager进行登录逻辑判断
return simpleAuthenticationInfo;
}
}
- controller层
@RequestMapping("login")
@ResponseBody
public String login(String username,String password){
try {
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
//登录成功就不会有异常
subject.login(usernamePasswordToken);
//判断是否有某个权限
subject.isPermitted("administrator");
//没有权限会报错,有权限就不报错
subject.checkPermission("administrator");
}catch (AuthenticationException e) {
e.printStackTrace();
}
return "success";
}
06_Shiro的授权
-
过滤器授权
在Shiro过滤器中对请求的url进行权限设置filterMap.put("/add.html","perms[adm:f:save]"); //设置未授权访问的页面路径—当权限不足时显示此页面 filter.setUnauthorizedUrl("/login.html");
-
注解授权
配置Spring对Shiro注解的支持:ShiroConfig.java
在请求的控制器添加权限注解@Controller @RequestMapping("list") public class CustomerController { @RequestMapping("save") //如果没有 adm:f:save 权限,则不允许执行此方法 @RequiresPermissions("adm:f:save") // @RequiresRoles("") public String list(){ System.out.println("----------->查询客户信息"); return "a"; } }
通过全局异常处理,指定权限不足时的页面跳转
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler public String doException(Exception e){ if(e instanceof AuthorizationException){ return "excep "; } return null; } }
-
手动授权
在代码中进行手动的权限校验Subject subject = SecurityUtils.getSubject(); if(subject.isPermitted("adm:f:save")){ return "有权限"; }else{ return "无权限"; }
- HTML授权
在菜单页面只显示当前用户拥有权限操作的菜单
07_Shiro的标签使用
当用户认证进入到主页面之后,需要显示用户信息及当前用户的权限信息;Shiro就提供了一套标签用于在页面来进行权限数据的呈现
Shiro提供了可供JSP使用的标签以及Thymeleaf中标签
- JSP页面中引用:
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
- Thymeleaf模版中引用:
在pom.xml文件中导入thymeleaf模版对shiro标签支持的依赖
在ShiroConfig中配置Shiro的<dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>
Thymeleaf模版中引入shiro的命名空间@Configuration public class ShiroConfig { @Bean public ShiroDialect getShiroDialect(){ return new ShiroDialect(); } //... }
<html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> ... </html>
07-1_常用标签
- guest,判断用户是否是游客身份,如果是游客身份则显示此标签内容
<shiro:guest> ····· </shiro:guest>
- user,判断用户是否是认证身份,如果是认证身份则显示此标签内容
- principal,获取当前登录用户名
<shiro:user> 用户[<shiro:principal/>]欢迎您! </shiro:user>
- hasRole,获取用户身份如果和name身份相等则显示此标签内容
<shiro:hasRole name="admin"> ····· </shiro:hasRole>
- hasPermission,获取用户权限如果和name权限相等则显示此标签内容
<shiro:hasPermission name="adm:f:save"> ····· </shiro:hasPermission>
08_Shiro的配置
08-1_Shiro使用加密认证
敏感信息存储数据库时需要利用Shiro加密认证
在realm中加入MD5Hash等加密规则即可Shiro会自动进行加密认证
08-2_缓存使用
使用Shiro进行权限管理过程中,每次授权都会访问realm中的doGetAuthorizationInfo方法查询当前用户的角色及权限信息,如果系统的用户量比较大则会对数据库造成比较大的压力
Shiro支持缓存以降低对数据库的访问压力(缓存的是授权信息)
08-3_session管理
Shiro进行认证和授权是基于session实现的,Shiro包含了对session的管理
- 如果需要对session进行管理
- 自定义session管理器
- 将自定义的session管理器设置给SecurityManager
08-4_记住我(rememberMe)
将用户对页面访问的权限分为三个级别:
- 未认证
- 记住我
- 已认证
08-1_退出登录
- 在Shiro过滤器中进行配置,配置logut对应的路径
filterMap.put("/exit","logout");
- 在页面的“退出”按钮上,跳转到logout对应的ur
<a href="exit">退出</a>
08-1_Shiro多Realm配置
多个Realm的处理方式:
- 链式处理(默认)
多个Realm依次进行认证,有一个Realm为true则结果为true - 分支处理
根据不同的条件从多个Realm中选择一个进行认证处理
Shiro的配置参考:
【Shiro】Shiro的MVC、SpringBoot整合配置及常用配置.
资料整合来自:Shiro官网.