1、shiro原理图如下:

框架解释:

subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。

securityManager:安全管理器,主体进行认证和授权都 是通过securityManager进行。它包含下面的认证器和授权器。

authenticator:认证器,主体进行认证最终通过authenticator进行的。

authorizer:授权器,主体进行授权最终通过authorizer进行的。

sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。可以实现单点登录。

SessionDao:  通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。

cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。

realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。(它的主要目的是与数据库打交道,查询数据库中的认证的信息(比如用户名和密码),查询授权的信息(比如权限的code等,所以这里可以理解为调用数据库查询一系列的信息,一般情况下在项目中采用自定义的realm,因为不同的业务需求不一样))

注意:在realm中存储授权和认证的逻辑。

cryptography:密码管理,提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。

比如 md5散列算法。

2、shiro介绍

shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权。

spring中有spring security (原名Acegi),是一个权限框架,它和spring依赖过于紧密,没有shiro使用简单。

shiro不依赖于spring,shiro不仅可以实现 web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。

使用shiro实现系统 的权限管理,有效提高开发效率,从而降低开发成本。

3、认证原理:

1、通过ini配置文件创建securityManager

2、调用subject.login方法主体提交认证,提交的token

3、securityManager进行认证,securityManager最终由ModularRealmAuthenticator进行认证。

4、ModularRealmAuthenticator调用IniRealm(给realm传入token) 去ini配置文件中查询用户信息

5、IniRealm根据输入的token(UsernamePasswordToken,即这里的token是用户从页面输入的信息)从 shiro-first.ini查询用户信息(这里是测试阶段,后面都是查询的数据库,注入service,调用dao),根据账号查询用户信息(账号和密码)

如果查询到用户信息,就给ModularRealmAuthenticator返回用户信息(账号和密码)

如果查询不到,就给ModularRealmAuthenticator返回null

6、ModularRealmAuthenticator接收IniRealm返回Authentication认证信息

如果返回的认证信息是null,ModularRealmAuthenticator抛出异常(org.apache.shiro.authc.UnknownAccountException)

如果返回的认证信息不是null(说明inirealm找到了用户),对IniRealm返回用户密码 (在ini文件中存在)和 token中的密码 进行对比,如果不一致抛出异常(org.apache.shiro.authc.IncorrectCredentialsException)

小结:

ModularRealmAuthenticator作用进行认证,需要调用realm查询用户信息(在数据库中存在用户信息)

ModularRealmAuthenticator进行密码对比(认证过程)。

realm:需要根据token中的身份信息去查询数据库(入门程序使用ini配置文件),如果查到用户返回认证信息,如果查询不到返回null。

4、 散列算法:

通常需要对密码 进行散列,常用的有md5、sha,

shiro的散列加密是这样子的:

建议对md5进行散列时加salt(盐),进行加密相当 于对原始密码+盐进行散列。

即md5+salt(这个盐一般是随机盐,即开发人员给定义随机的字符串或者数字即可)+散列次数

这里的md5是原始的md5的加密了一次的密码+随机盐,然后对这个新的密码password=(md5+salt),进行散列:如何进行散列呢:就是多次md5加密md5(md5(md5(md5(password)))),这是4次散列,每次密码的破解的难度都加大。

正常使用时散列方法:

在程序中对原始密码+盐进行散列,将散列值存储到数据库中,并且还要将盐也要存储在数据库中。

如果进行密码对比时,使用相同 方法,将原始密码+盐进行散列,进行比对。

5、授权原理

原理:

1、对subject进行授权,调用方法isPermitted("permission串")

2、SecurityManager执行授权,通过ModularRealmAuthorizer执行授权

3、ModularRealmAuthorizer执行realm(自定义的CustomRealm)从数据库查询权限数据

调用realm的授权方法:doGetAuthorizationInfo

4、realm从数据库查询权限数据,返回ModularRealmAuthorizer

5、ModularRealmAuthorizer调用PermissionResolver进行权限串比对

6、如果比对后,isPermitted中"permission串"在realm查询到权限数据中,说明用户访问permission串有权限,否则 没有权限,抛出异常。

shiro的授权方式有三种:

(1)—— 编程式:通过写if/else 授权代码块完成:(这种比较少用,一般在项目中采用后两种)

Subject subject = SecurityUtils.getSubject();

if(subject.hasRole(“admin”)) {

//有权限

} else {

//无权限

}

(2)——  注解式:通过在执行的Java方法上放置相应的注解完成:

@RequiresRoles("admin")

public void hello() {

//有权限

}

(3)——  JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成:

在jsp页面导入shiro的标签既可以使用shiro的标签来进行权限的判断:

Jsp页面添加:

<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>

标签名称

标签条件(均是显示标签内容)

<shiro:authenticated>

登录之后

<shiro:notAuthenticated>

不在登录状态时

<shiro:guest>

用户在没有RememberMe时

<shiro:user>

用户在RememberMe时

<shiro:hasAnyRoles name="abc,123" >

在有abc或者123角色时

<shiro:hasRole name="abc">

拥有角色abc

<shiro:lacksRole name="abc">

没有角色abc

<shiro:hasPermission name="abc">

拥有权限资源abc

<shiro:lacksPermission name="abc">

没有abc权限资源

<shiro:principal>

显示用户身份名称

<shiro:principal property="username"/>     显示用户身份中的属性值

<shiro:hasRole name="admin">

<!— 有权限—>

</shiro:hasRole>

6、shiro与项目的整合:

整合无非就是jar包和配置文件:

配置文件:在web.xml中配置filter:

在web系统中,shiro也通过filter进行拦截。filter拦截后将操作权交给spring中配置的filterChain(过虑链儿)

shiro提供很多filter。 在web.xml中配置filter

与spring的整合交由spring的容器管理:security manager 、realm、filter都交由spring整合

下面可以看下具体realm自定义使用与application_shiro的内容:

realm:

package cn.project.ssm.shiro;import java.security.acl.Permission;
import java.util.ArrayList;
import java.util.List;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;import com.sun.org.apache.bcel.internal.generic.ACONST_NULL;import cn.project.ssm.pojo.ActiveUser;
import cn.project.ssm.pojo.SysPermission;
import cn.project.ssm.pojo.SysUser;
import cn.project.ssm.service.LoginService;/*** * <p>* Title: CustomRealm* </p>* <p>* Description:自定义realm,实际开发中一般都是自定义realm* </p>* <p>* Company: www.itcast.com* </p>* * @date 2015-3-23下午4:54:47* @version 1.0*/
public class CustomRealm extends AuthorizingRealm {@Autowiredprivate LoginService loginService;// 设置realm的名称@Overridepublic void setName(String name) {super.setName("customRealm");}//用于认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//第一步:从token中取出用户名,这个用户名是用户在页面输入的信息,传递给tokenString userCode=(String) token.getCredentials();//根据用户名查询用户信息SysUser sysUser=null;sysUser=loginService.findByUserCode(userCode);if (sysUser==null) {return null; }String password=sysUser.getPassword();//加盐String salt=sysUser.getSalt();//将用户身份信息写入activeUserActiveUser activeUser=new ActiveUser();activeUser.setUserid(sysUser.getId());activeUser.setUsercode(sysUser.getUsercode());activeUser.setUsername(sysUser.getUsername());//通过service取出菜单List<SysPermission> menus= loginService.findmenusByUserId(sysUser.getId());activeUser.setMenus(menus);//写到这里我们看到realm其实主要是从数据库中获取数据SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(activeUser,password,ByteSource.Util.bytes(salt), this.getName());return simpleAuthenticationInfo;}//用于授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {//从princal中获取主身份信息,将返回值转为真实的身份信息,填充到上面认证的身份中ActiveUser activeUser=(ActiveUser) principal.getPrimaryPrincipal();//从数据库中获取到权限数据List<SysPermission> permissionsList = loginService.findpermissionByUserId(activeUser.getUserid());List<String> permissions=new ArrayList<>();for (SysPermission sysPermission : permissionsList) {permissions.add(sysPermission.getPercode());}//将集合内容填充认证中SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();simpleAuthorizationInfo.addStringPermissions(permissions);return simpleAuthorizationInfo;}//清除缓存public void clearCached() {PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();super.clearCache(principals);}}

  配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "><!-- web.xml中shiro的filter对应的bean -->
<!-- Shiro 的Web过滤器 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager" /><!-- loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 --><property name="loginUrl" value="/login.action" /><!-- 认证成功统一跳转到first.action,建议不配置,shiro认证成功自动到上一个请求路径 --><!-- <property name="successUrl" value="/first.action"/> --><!-- 通过unauthorizedUrl指定没有权限操作时跳转页面--><property name="unauthorizedUrl" value="/refuse.jsp" /><!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 --><property name="filterChainDefinitions"><value> <!-- 对静态资源设置访问,不然都拦截了 -->/images/**=anon/js/**=anon/styles/**=anon<!-- 请求logout.action地址,shiro清除session -->/logout.action=logout<!-- /** = authc所有url都可以认证通过才能访问 -->   /** = authc<!-- /** = anon所有url都可以匿名访问 -->  /** = anon             </value></property></bean><!-- securityManager安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="customRealm" />   <!-- 注入缓存管理器 --><property name="cacheManager" ref="cacheManager"/></bean><!-- realm -->
<bean id="customRealm" class="cn.project.ssm.shiro.CustomRealm"><!-- 将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列 --><property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean><!-- 散列加盐凭证匹配器 -->
<bean id="credentialsMatcher"class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><property name="hashAlgorithmName" value="md5" /><property name="hashIterations" value="1" />
</bean>
<!-- 缓存管理器 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"><property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/></bean>
</beans>

  

shiro的原理理解相关推荐

  1. Shiro(三) Shiro核心原理分析

    一.Shiro登陆认证原理 对于登陆请求(URL=/login.html),我们一般使用"anno"拦截器去过滤处理,而这个filter又是放行所有资源的(不作任何处理),所以登陆 ...

  2. Linux 输入子系统原理理解(原创)

    linux    输入子系统原理理解(原创) 以前学了单独的按键设备驱动以及鼠标驱动,实际上,在linux中实现这些设备驱动,有一种更为推荐的方法,就是input输入子系统.平常我们的按键,触摸屏,鼠 ...

  3. 集成学习——NGBoost论文研读与原理理解

    NGBoost(Natural Gradient Boosting)是一个比较新的Boosting方法,它是2019年10月斯坦福吴恩达团队在arXiv上发表的,论文连接为:NGBoost: Natu ...

  4. 集成学习—GBDT原理理解

    GBDT,全称为梯度提升决策树,即Gradient Boosting Decision Tree.上一篇博客:集成学习-GBDT(论文研读)中已经对GBDT原始论文--Jerome H. Friedm ...

  5. 2021-08-06随记(vertical-align, 顶线、底线、中线、基线,vue原理理解)

    vertical-align 父元素是inline或者是table-cel,如果是inline-block或者block则必须要设置line-height(和高度一样)子元素为inline或者inli ...

  6. win10自动修复无法修复你的电脑的解决方法(操作+原理理解)

    目录 前言 步骤与原理 疑惑 总结 参考文献 前言 早起开机,突遇下面问题,以为重启即可,后来无济于事,于是查找资料,找到了解决方法,给出了具体操作,更重要的是其中一些操作语句的原理理解,因为每个人出 ...

  7. 【Educoder作业】冯·诺依曼体系结构及工作原理理解

    [Educoder作业]冯·诺依曼体系结构及工作原理理解 所有的那个实际场景模拟的题就不更了,没难度,趣味性更高. 这个题和我们之前的一篇博客里面的题只一模一样的,链接. 我们这里就不做任何讲解了,要 ...

  8. 计算机原理理解编程语言_计算机如何理解我们对编程语言及其工作原理的高级概述...

    计算机原理理解编程语言 Many folks have at one point or another asked themselves how a computer really understan ...

  9. shiro漏洞原理以及检测key值原理

    一.shiro漏洞原理 Shiro 1.2.4及之前的版本中,AES加密的密钥默认硬编码在代码里(SHIRO-550),Shiro 1.2.4以上版本官方移除了代码中的默认密钥,要求开发者自己设置,如 ...

  10. Shiro大概原理和快速开始

    Shiro大概原理和快速开始 shiro快速开始-helloshiro(官网教程:http://shiro.apache.org/10-minute-tutorial.html) 1.下载 shiro ...

最新文章

  1. 首发 | 旷视14篇CVPR 2019论文,都有哪些亮点?
  2. mysql数据导库常用操作
  3. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二十五)完美捕捉精灵之神器 -- HitTest...
  4. 【ARM】一步一步移植Linux Kernel 2.6.13到板子
  5. kibana升级之后原本保存的数据dashboards, visualizations, index patterns丢失
  6. 开启HDR视觉盛宴:究竟什么视频算得上HDR?
  7. C语言满分:L1-061 新胖子公式 (10分)
  8. JENKINS使用DOCKER运行PYTEST并且出ALLURE报告
  9. 获取指定路径下所有PDF文件的总页数
  10. 自定义条件查询_跟我学shardingjdbc之自定义分库分表策略-复合分片算法自定义实现...
  11. 高性能Mysql中文版
  12. UCSC Xena:癌症基因组学数据分析平台
  13. 数学中倒三角:梯度;正三角:拉普拉斯
  14. Balanced Array
  15. 基于Impala的网易有数BI查询优化总结
  16. python实现京东商城
  17. 嵌入式软件常见笔试面试题
  18. 微信小程序、苹果手机(ios)时间格式显示NAN.....(已解决)
  19. 联邦学习 | 无处不在的隐私泄露!
  20. 设计一个靠谱的监控告警平台

热门文章

  1. Python学习笔记-2017.5.4thon学习笔记-2017.5.19
  2. 性能测试实战(二):性能测试基础
  3. STM32F401CCU6移植华为LiteOS
  4. 服务器基线扫描修复,怎么对服务器进行基线和漏洞扫描
  5. 一招教你如何调整图片的分辨率DPI?
  6. 1.3.1 计算机的主要性能指标 (机器字长、数据通路带宽、主存容量、运算速度、吞吐量、响应时间、主频和时钟周期、CPI、CPU执行时间、MIPS、MFLOPS、GFLOPS、TFLOPS)
  7. RTOS那些你得知道的事儿(一)
  8. Google趋势(Trends)有趣的关键词
  9. 与阿里合伙人合影,两年净赚一百万,这个草根姑娘有什么魔力?
  10. 信息录入率百分百上海强化施工现场建筑工人实名制管理