Shiro学习与笔记

Posted 霏ིྀ宇ིྀ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shiro学习与笔记相关的知识,希望对你有一定的参考价值。

Shiro

Shiro

Shiro理论

什么是shiro

Shiro是一个强大易用的java安全,提供了认证、授权、加密、会话管理、与web集成、缓存等功能,对于任何一个应用程序,都可以提供全面的安全服务,相比其他安全框架,shiro要简单的多。

功能

  • 身份验证(核心功能);
  • 资源授权(核心功能);
  • 密码加密(非核心功能);
  • 会话管理(非核心功能);
  • Remember Me(非核心功能);

组件

  • Subject:应用层和shiro框架交互的对象
  • Realm:实现身份验证和资源授权的核心组件:域,shiro从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。
  • RememberMeManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject;可以看出它是shiro的核心, SecurityManager相当于spring mvc中的dispatcherServlet前端控制器。
    • SimpleCookie:记住我——Cookie
    • CookieRememberMeManager:记住我—— Cookie 管理器;
  • SessionManager
    • SimpleCookie:会话管理—— Cookie
    • DefaultWebSessionManager:会话配置;
  • SecurityManager:安全管理器,它负责与 Shiro 的其他组件进行交互,需要注入 RealmRememberMeManagerSessionManager 等组件,且管理着所有的 Subject;
  • ShiroFilterFactoryBeanShiro 过滤器工厂,注入 SecurityManager、定义过滤器、指定路径拦截规则等;
  • ShiroDialect:Shiro 方言,支持 Thymeleaf 页面 Shiro 标签;
  • DefaultAdvisorAutoProxyCreator:Advisor 代理类生成器;
  • AuthorizationAttributeSourceAdvisor:创建 Advisor 代理类,扫描 Shiro 注解;
  • 应用代码通过 Subject 来进行认证和授权,Subject 委托给 SecurityManager,我们需要给 Shiro 的 SecurityManager 注入 Realm,从而让 SecurityManager 能对用户及其权限进行判断;

shiro注解

  • @RequiresAuthentication : 表示当前 Subject 需要登录;
  • @RequiresUser : 表示当前 Subject 需要登录或记住我;
  • @RequiresGuest : 表示当前 Subject 是游客身份;
  • @RequiresRoles(value=“admin”, “user”, logical=Logical.AND):当前 Subject 需要的角色;
  • @RequiresPermissions (value=““,””, logical= Logical.OR) :当前 Subject 需要拥有的资源;

既可以用在controller中,也可以用在service中建议将shiro注解放入controller,因为如果service层使用了spring的事物注解,那么shiro注解将无效

shiro的优点

1、 简单的身份验证,支持多种数据源
2、对角色的简单授权,支持细粒度的授权(方法)
3、支持一级缓存,以提升应用程序的性能
4、内置基于POJO的企业会话管理,适用于web及非web环境
5、非常简单的API加密
6、不跟任何框架绑定,可以独立运行

运行流程

  1. 首先调用 Subject.login(token) 进行登录,其会自动委托给 Security Manager,调用之前必须通过 SecurityUtils.setSecurityManager() 设置;
  2. SecurityManager 负责真正的身份验证逻辑;它会委托给 Authenticator 进行身份验证;
  3. Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,此处可以自定义插入自己的实现;
  4. Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认 ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份验证;
  5. Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返回 则抛出异常表示身份验证失败了。此处可以配置多个 Realm,将按照相应的顺序及策略进行访问。

前端标签

jsp页面

首先要导入标签库;
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>:导入标签库;
    
<shiro:guest></shiro:guest>:游客访问;
    
<shiro:user></shiro:user>:用户需要登录或记住我;
    
<shiro:authenticated></shiro:authenticated>:用户需要登录;
    
<shiro:hasRole name="admin"></shiro:hasRole>:用户需要拥有某种角色访问;
    
<shiro:hasAnyRoles name="admin,user"></shiro:hasAnyRoles>:用户需要拥有某些角色;
    
<shiro:hasPermission name="user:create"></shiro:hasPermission>:用户需要拥有某资源;进行显示
    

Thymeleaf

导入
<html 
       xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"
      >
    
</html>

shiro:guest:游客访问;
shiro:user:用户需要登录或记住我;
shiro:authenticated:用户需要登录;
shiro:hasRole:用户需要某角色;
shiro:hasAnyRoles:用户需要某些角色;
shiro:hasPermission:用户需要某权限;
-----------------------------------------------------------
<li shiro:hasAnyRoles="admin,manager">:用户需要 admin 或 manager 角色可访问;
    
<li><span shiro:principal/></li>:身份验证器包装的用户名时,页面获取用户名;

<span shiro:principal property="loginName"/>:身份验证器中包装 user 对象时,页面获取用户名;

<input type="hidden" id="userId" th:value="$session.user.userId">:页面获取 session 中 user 对象;

在spring框架中集成shiro

Pom文件进行依赖配置

可以在maven仓库包https://mvnrepository.com/,根据三要素进行查找

<!-- shiro -->
<properties>
    <shiro.version>1.7.1</shiro.version>
</properties>
<!-- shiro配置 -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>$shiro.version</version>
    </dependency>

<!-- 支持Spring框架集成-->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>$shiro.version</version>
    </dependency>

<!-- 支持基于web的应用程序 -->
<dependency>
  <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-web</artifactId>
   <version>$shiro.version</version>
</dependency>

<!-- 启用对Shiro AOP和注释的AspectJ支持。 -->
<dependency>
  <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-aspectj</artifactId>
   <version>$shiro.version</version>
</dependency>

<!-- 启用基于ehcache的框架缓存。 -->
<dependency>
  <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-ehcache</artifactId>
   <version>$shiro.version</version>
</dependency>

项目跑起来了,只是控制台输出了

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

需要配置日志包

shiro使用slf4j作为日志框架,所以必需配置slf4j。同时,使用log4j作为底层的日志实现框架。

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.25</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.7.25</version>
</dependency>
<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.2.17</version>
</dependency>

集成Shiro

在Spring框架中集成Shiro,本质上是与Spring IoC容器和Spring MVC框架集成.

web.xml中的设置

  <!-- shiro过滤器 -->
  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <!-- 设置true由servlet容器控制filter的生命周期 -->
    <!--官方解释到,支持targetBeanName 通过 init-param 这个节点来设置-->
    <init-param>
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

shiro的bean配置文件,

其中包含过滤设置。此文件名为spring-shiro.xml,里面定义了需要的Bean,完成诸多功能。

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
	   http://www.springframework.org/schema/context/spring-context-4.3.xsd

">   
    <!-- 这些类注册为spring容器中的bean-->
    <context:component-scan base-package="com.qq"/>
    
     <!--注入自定义的Realm-->
    <bean id="userRealm" class="com.qq.realm.UserRealm"/>
    
    <!--开启shiro的注解-->
    <bean id="advisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
        <!--必须 否则shiro就无法解析权限url-->
        <property name="proxyTargetClass" value="true"/>
    </bean>
    
    <!-- Shiro 生命周期处理器 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- DefaultAdvisorAutoProxyCreator, Advisor 代理类生成器 -->
    
    <!--让RequiredPermissions生效-->
     <!-- 创建 AuthorizationAttributeSourceAdvisor,扫描 Shiro 注解 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/> <!-- 这句可能要打开才能启用注解 -->
    </bean>
    
    <!-- Security Manager -->
       <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--        定义了认证逻辑和授权逻辑-->
        <property name="realm" ref="userRealm"/>
    </bean>
    
    
     <!-- Shiro的Web过滤器 id 必须 和web.xml文件中配置的一致-->
    <!--配置ShiroFilter-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

        <!-- Shiro的安全管理器,所有关于安全的操作都会经过SecurityManager -->
      <property name="securityManager" ref="securityManager"/>

      <!-- 认证页面:未认证用户请求需要认证的url时就会自动跳转到此页面url。-->
        <!-- 它不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的"/login.jsp"。-->
        <property name="loginUrl" value="/login/view"/>

        <!-- 没有授权的用户请求需要授权的url时就会被跳转到这个地址 -->  <!-- 但是我发现这句不起作用 -->
        <property name="unauthorizedUrl" value="/login/view" />

        <!-- 认证成功页面url:-->
        <!-- 理想状况下,它是认证成功后默认跳转路径,不设置则跳转至"/"。-->
        <!-- 理想状况下,如果点击一个需认证的url,经认证后则会自动跳转到之前这个需要认证的url,而不跳到successUrl。-->
        <!-- 但上面所说的仅是理想状况下 successUrl的功效。实验时往往差强人意-->
        <property name="successUrl" value="/home"/>

        <!--
        <property name="filters">
            <map>
                <entry key="logout" value-ref="logoutFilter" />
            </map>
        </property>
         -->

        <!-- URL的过滤规则指定-->
        <!-- 用得最多的是  
           anon(匿名可访问),
           authc(认证后可访问),
           logout(注销时用)
        (会清除所有sesseion和一些cookie)(会默认跳往根目录) 
         user:登录过能访问
         roles:角色过滤器
         -->
        <property name="filterChainDefinitions" >
            <value>
                /login/view = anon
                /back/student/zzz =authc,roles[admin]
                /back/** = authc
            </value>
        </property>


   
</beans>


或者:springShiro.xml


<?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:context="http://www.springframework.org/schema/context" 

    xsi:schemaLocation="http://www.springframework.org/schema/beans 

            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 

            http://www.springframework.org/schema/context  

            http://www.springframework.org/schema/context/spring-context-4.0.xsd"

    default-lazy-init="true">

    

    <!-- Realm 配置 -->

    <bean id="myRealm" class="com.sfac.springMvc.config.MyRealm" />

    

    <!-- Remember Me 配置 -->

    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">

        <property name="name" value="rememberMe"/>

        <property name="maxAge" value="604800"/>

        <property name="httpOnly" value="true"/>

    </bean>

    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">

        <property name="cookie" ref="rememberMeCookie"/>

    </bean>

    

    <!-- Session 配置 -->

    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">

        <!-- Session 的失效时长,单位毫秒 -->

        <property name="globalSessionTimeout" value="6000000"/>

        <!-- 删除失效的 Session -->

        <property name="deleteInvalidSessions" value="true"/>

        <!-- 去掉重定向后 Url 追加 Session Id -->

        <property name="sessionIdUrlRewritingEnabled" value="false" />

    </bean>

    

    <!-- Security Manager -->

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  

        <property name="realm" ref="myRealm"/>

        <property name="rememberMeManager" ref="rememberMeManager"></property>

        <property name="sessionManager" ref="sessionManager" />

    </bean>

    

    <!-- 

        Shiro Filter 

        anon:匿名访问,无需登录

        authc:登录后才能访问

        user:登录过能访问

        logout:登出

        roles:角色过滤器

    -->

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

        <property name="securityManager" ref="securityManager"/>

        <property name="loginUrl" value="/login"/>

        <property name="successUrl" value="/common/dashboard"/>

        

        <property name="filterChainDefinitions">  

            <value>  

                /static/**=anon

                /register=anon

                /login=anon

                /forgot=anon

                /logout=logout

                /api/**=anon

                /**=authc

            </value>  

        </property>  

    </bean>

    

    <!-- 配置验证表单名称,默认是:userName,password -->

    <!-- <bean id="authc" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
        <property name="usernameParam" value="account"></property>
        <property name="passwordParam" value="password"></property>

    </bean> -->

    

    <!-- Shiro 生命周期处理器 -->

    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <!-- DefaultAdvisorAutoProxyCreator, Advisor 代理类生成器 -->

    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"

        depends-on="lifecycleBeanPostProcessor">

        <property name="proxyTargetClass" value="true" />

    </bean>

    <!-- 创建 AuthorizationAttributeSourceAdvisor,扫描 Shiro 注解 -->

    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">

        <property name="securityManager" ref="securityManager" />

    </bean>

</beans>

必须是在MVC配置文件中用

<import resource=*"spring-shiro.xml"*></import>

将spring-shiro.xml载入。

例子: