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 的其他组件进行交互,需要注入 Realm、RememberMeManager、SessionManager 等组件,且管理着所有的 Subject;
- ShiroFilterFactoryBean:Shiro 过滤器工厂,注入 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、不跟任何框架绑定,可以独立运行
运行流程
- 首先调用
Subject.login(token)
进行登录,其会自动委托给Security Manager
,调用之前必须通过SecurityUtils.setSecurityManager()
设置; SecurityManager
负责真正的身份验证逻辑;它会委托给Authenticator
进行身份验证;Authenticator
才是真正的身份验证者,Shiro API
中核心的身份认证入口点,此处可以自定义插入自己的实现;Authenticator
可能会委托给相应的AuthenticationStrategy
进行多 Realm 身份验证,默认ModularRealmAuthenticator
会调用AuthenticationStrategy
进行多 Realm 身份验证;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载入。
例子:
-
身份验证
UserRealm
package com.qq.realm; import com.qq.model.User; import com.qq.service.UserService; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollect
以上是关于Shiro学习与笔记的主要内容,如果未能解决你的问题,请参考以下文章