shiro框架

1.shiro与spring+springmvc整合

实际开发中,web项目都是使用的ssm架构,一般都会整合项目安全框架shiro
1.1创建新工程
创建基于maven的工程
在这里插入图片描述
1.2导入maven项目相关依赖

<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>cn.zj</groupId>
	<artifactId>spring-shiro</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

<properties>
	<spring.version>4.3.2.RELEASE</spring.version>
	<slf4j.version>1.6.6</slf4j.version>
	<log4j.version>1.2.17</log4j.version>
	<shiro.version>1.2.3</shiro.version>
</properties>
<dependencies>
	<!-- spring -->
	<dependency>
		<groupId>org.aspectj</groupId>
		<artifactId>aspectjweaver</artifactId>
		<version>1.7.4</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-tx</artifactId>
		<version>${spring.version}</version>
	</dependency>

	<!-- log4j日志 -->
	<dependency>
		<groupId>log4j</groupId>
		<artifactId>log4j</artifactId>
		<version>${log4j.version}</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-api</artifactId>
		<version>${slf4j.version}</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-log4j12</artifactId>
		<version>${slf4j.version}</version>
	</dependency>

	<!-- 连接池 -->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid</artifactId>
		<version>1.1.10</version>
	</dependency>
	<!-- mybatis -->
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis</artifactId>
		<version>3.4.4</version>
	</dependency>
	<!-- mybatis和spring集成包 -->
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis-spring</artifactId>
		<version>1.3.2</version>
	</dependency>



	<!-- 加入servlet和jsp的依赖 -->
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>javax.servlet-api</artifactId>
		<version>3.1.0</version>
		<scope>provided</scope>
	</dependency>

	<dependency>
		<groupId>javax.servlet.jsp</groupId>
		<artifactId>javax.servlet.jsp-api</artifactId>
		<version>2.2.1</version>
		<scope>provided</scope>
	</dependency>


	<!-- 引入shiro框架的依赖 -->
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-core</artifactId>
		<version>${shiro.version}</version>
	</dependency>
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-web</artifactId>
		<version>${shiro.version}</version>
	</dependency>
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-spring</artifactId>
		<version>${shiro.version}</version>
	</dependency>
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-quartz</artifactId>
		<version>${shiro.version}</version>
	</dependency>
	<!-- shiro和spring集成包 -->
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-spring</artifactId>
		<version>${shiro.version}</version>
	</dependency>
	<!-- MySQL数据库驱动依赖 -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.26</version>
	</dependency>
</dependencies>
<build>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-surefire-plugin</artifactId>
			<version>2.22.1</version>
			<configuration>
				<skipTests>true</skipTests>
			</configuration>
		</plugin>
	</plugins>
</build>
</project>

1.3web.xml中配置shiro的filter
在web系统中,shiro也通过filter进行拦截。filter拦截后将操作权交给sprin,g中配置的filterChainDefitions,shiro提供很多filter

<!-- Shiro过滤器,DelegatingFilterProxy类是为了让代理模式将spring和Shiro的过滤器关联起来-->
<filter>
   <filter-name>shiroFilter</filter-name>
   <filter-class>org.springframeword.web.filter.DelegatingFilterProxy</filter-class>
   <!--设置为true以后filter的生命周期交给servlet管理-->
   <init-param>
       <param-name>targetFilterLifecycle</param-name>
       <param-value>ture</param-value>
   </init-param>
   

1.4 spring-shiro.xml
在spring-shiro.xml 中配置web.xml中fitler对应spring容器中的bean。

<bean id="shiroFilter"
	class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	<!-- 注入安全管理器 -->
	<property name="securityManager" ref="securityManager" />

	<!-- 注入认证页面, 如果访问一个页面没有认证,会自动跳转到此页面进行认证 -->
	<property name="loginUrl" value="/login.do" />

	<!-- 注入认证成功页面 -->
	<property name="successUrl" value="/index.do" />


	<!-- 认证通过,没有权限访问跳转到的页面 -->
	<property name="unauthorizedUrl" value="/unauthorized.jsp" />
	<!-- 设置shiro的过滤器链 ,过滤器链的顺序从上到下执行 所有 一般 /**最好配置到最后面 -->
	<property name="filterChainDefinitions">
		<value>
			<!-- 放行静态资源 -->
			/images/**=anon
			/js/**=anon
			/css/**=anon
			
			/login.jsp = anon
			<!-- logout:退出登录过滤器,清除Session数据 -->
			/logout.do=logout
			<!-- /**所有请求 ,authc 表示所有请求都需要认证通过才可以访问 -->
			/** = authc
		</value>
	</property>
</bean>

1.5.静态资源
对静态资源设置逆名访问:
修改spring-shiro.xml:

<property name="filterChainDefinitions">
			<value>
				<!-- 放行静态资源 -->
				/images/**=anon
				/js/**=anon
				/css/**=anon
		</value>
   </property> 

1.6.认证-登陆
1.6.1.登录原理
用户点击登录提交到 的 /user/login.do 匹配到shiro的 /**
/** 使用的表单认证过滤器 FormAuthenticationFilter ,此过滤器内部会获取当前用户提交的表单的
账号和密码(注意:账号表单名称一定叫做username,密码表单名称一定叫password),封装到token令牌中,并且调用自定义的Realm中的doGetAuthenticationInfo
方法,进行认证,
1.如果认证通过,直接跳转到
后台首页
2.如果认证失败,跳转到

并且把认证失败的错误异常类型,设置HttpServletRequest请求对象中,作用域的名称就是
FormAuthenticationFilter 中 shiroLoginFailure
我们可以在/user/login.do中注入一个HttpServletRequest接收这个错误信息

1.6.2.登陆页面
由于FormAuthenticationFilter的用户身份和密码的input的默认值(username和password),修改页面的账号和密码 的input的名称为username和password

1.6.3.登陆代码实现
import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/user")
public class UserController {

@RequestMapping("/login")
public String login(HttpServletRequest request,Model m) {
	
	//获取认证失败的错误信息,在Shiro框架的 FormAuthenticationFilter 过滤器中共享
	// 共享的属性名称  shiroLoginFailure
	// 共享的 shiro 异常的字节码 类型
	String shiroLoginFailure = (String) request.getAttribute("shiroLoginFailure");
	System.out.println("异常类型 :"+shiroLoginFailure);
	if(shiroLoginFailure !=null) {
		
		if(UnknownAccountException.class.getName().equals(shiroLoginFailure)) {
			m.addAttribute("erroyMsg", "亲。账号不存在");
		}else if(IncorrectCredentialsException.class.getName().equals(shiroLoginFailure)) {
			m.addAttribute("erroyMsg", "亲。密码错误");
		}
		
	}
	return "forward:/login.jsp";
}
}

1.6.4.认证拦截过虑器

在spring-shiro.xml中配置-

<bean id="shiroFilter"
	class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	<!-- 注入安全管理器 -->
	<property name="securityManager" ref="securityManager" />

	<!-- 注入登录页面, 如果没有认证,会自动跳转到此页面进行认证 -->
	<property name="loginUrl" value="/login.do" />

	<!-- 注入认证成功页面 -->
	<property name="successUrl" value="/index.do" />


	<!-- 认证通过,没有权限访问跳转到的页面 -->
	<property name="unauthorizedUrl" value="/unauthorized.jsp" />
	<!-- 设置shiro的过滤器链 ,过滤器链的顺序从上到下执行 所有 一般 /**最好配置到最后面 -->
	<property name="filterChainDefinitions">
		<value>
			<!-- 放行静态资源 -->
			/images/**=anon
			/js/**=anon
			/css/**=anon
			
			/login.jsp = anon
			<!-- logout:退出登录过滤器,清除Session数据 -->
			/logout.do=logout
			<!-- /**所有请求 ,authc 表示所有请求都需要认证通过才可以访问 -->
			/** = authc
		</value>
	</property>
</bean>

<!-- 配置安全管理器 -->
<bean id="securityManager"
	class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	<!-- 配置realms -->
	<property name="realm" ref="customRealm" />
</bean>

<!-- 配置自定义realm -->
<bean id="customRealm" class="cn.zj.shiro.realm.CustomRealm">
	<!-- 注入凭证匹配器 -->
	<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="2" />
</bean>

1.6.5.测试认证代码
登录一个认证过程,在自定义的realm中开发者自己完成认证操作
认证思路
1.根据账号查询数据库对应的用户信息并封装成对象
2.获取用户对象对应的密码,和登录操作提交的用户密码进行(加盐+散列)后就进行比对
3.返回认证对象
(1)如果认证成功,会跳转到成功页面一般是首页
(2)如果认证失败,继续认证
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.authc.UsernamePasswordToken;
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;

public class CustomRealm extends AuthorizingRealm {

/**
 * 认证方法,开发者自己实现具体认证操作 如果认证成功,返回一个 AuthenticationInfo 封装有认证对信息的对象
 * 
 */
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
	// 1.获取token的身份信息(账号)--用户输入
	String principal = (String) token.getPrincipal();// 当事人(当前登录的账号)
	UsernamePasswordToken uToken = (UsernamePasswordToken) token;
	// 认证思路
	// --1.根据账号从数据库中查询出是否有此账号,有封装成一个对象,没有返回null
	// --2.如果有的对象的话,把对象的密码作为品质传递到下面认证对象中进行认证操作
	// 模拟从数据库中查询的的(凭证)密码
	String hashedCredentials = "662b46d0168aa5353771f45084378881";

	String stla = "query";

	// 3.创建返回认证信息的对象
	ByteSource credentialsSalt = ByteSource.Util.bytes(stla);
	//数据库 身份 账号
	String principal = "admin";
	
	System.out.println("principals :"+principal);
	
	if("admin".equals(username)) {
		
		//加密后的 认证信息对象
		SimpleAuthenticationInfo authenticationInfo = new  SimpleAuthenticationInfo(principal, hashedCredentials, credentialsSalt, this.getName());	
		return authenticationInfo;
	}
	
	return null;
}

//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

	return null;
}

}

1.7.认证信息在页面显示
1、认证后用户菜单在首页显示
2、认证后用户的信息在页头显示

1.7.1.认证成功以后的首页
一般认证成功以后,都跳转到首页,首页一般显示菜单用户登录信息,和用户操作其他模块相关界面

import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {

	@RequestMapping("/index.do")
	public String list(HttpServletRequest req, Model model) {
		return "index";
	}
}

1.8.退出

1.8.1.使用LogoutFilter
不用我们去实现退出,只要去访问一个退出的url,由LogoutFilter拦截住,清除session。
在spring-shiro.xml配置LogoutFilter

<bean id="shiroFilter"
	class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	<!-- 注入安全管理器 -->
	<property name="securityManager" ref="securityManager" />

	<!-- 注入登录页面, 如果没有认证,会自动跳转到此页面进行认证 -->
	<property name="loginUrl" value="/user/login.do" />

	<!-- 注入认证成功页面 -->
	<property name="successUrl" value="/index.do" />


	<!-- 认证通过,没有权限访问跳转到的页面 -->
	<property name="unauthorizedUrl" value="/unauthorized.jsp" />
	<!-- 设置shiro的过滤器链 ,过滤器链的顺序从上到下执行 所有 一般 /**最好配置到最后面 -->
	<property name="filterChainDefinitions">
		<value>
			<!-- 放行静态资源 -->
			/images/**=anon
			/js/**=anon
			/css/**=anon
			
			/login.jsp = anon
			<!-- logout:退出登录过滤器,清除Session数据 -->
			/logout.do=logout
			<!-- /**所有请求 ,authc 表示所有请求都需要认证通过才可以访问 -->
			/** = authc
		</value>
	</property>
</bean>

1.8.2.Controller方法

@RequestMapping("/logout.do")
	public String logout() {
		return "redirect:/login.jsp";
	}

1.9.shiro的过虑器
在这里插入图片描述
1、anon:例子/admins=anon 没有参数,表示可以匿名使用。
2、authc:例如/admins/user=authc表示需要认证(登录)才能使用,FormAuthenticationFilter是表单认证,没有参数
3、perms:
(1)例子/admins/user=perms[user:add:],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user=perms["user:add:,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
4、user:例如/admins/user/**=user没有参数表示必须存在用户, 身份认证通过或通过记住我认

1.9.1.设置凭证匹配器
数据库中存储到的md5的散列值,在realm中需要设置数据库中的散列值它使用散列算法 及散列次数,让shiro进行散列对比时和原始数据库中的散列值使用的算法 一致。

<!-- 配置凭证匹配器 -->
<bean id="credentialsMatcher"
	class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
	<!-- 加密算法 -->
	<property name="hashAlgorithmName" value="md5" />
	<!-- 散列次数 -->
	<property name="hashIterations" value="2" />
</bean>

1.10.授权
1.10.1.在自定义Realm中授权
授权思路,从当前登录用户信息中获取用户的所有权限,并添加到 SimpleAuthorizationInfo对象中
如果shiro配置的授权表达式匹配到了,授权成功,放行。如果没有匹配,跳转到没有权限访问提示页面

//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
	SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
	
	//授权思路,从当前登录用户信息中获取用户的所有权限,并添加到 SimpleAuthorizationInfo对象中
	//如果shiro配置的授权表达式匹配到了,授权成功,放行。如果没有匹配,跳转到没有权限访问提示页面
	
	authorizationInfo.addStringPermission("user:list");
	authorizationInfo.addStringPermission("role:list");
	authorizationInfo.addStringPermission("permission:list");
	return authorizationInfo;
}

1.10.2.使用PermissionsAuthorizationFilter 方式
在spring-shiro.xml中配置url所对应的权限。

1、在spring-shiro.xml中配置filter规则
(1)/user/update.do=perms[user:update]
(2)/user/list.do=perms[user:list]
2、用户在认证通过后,请求/user/list.do
3、被PermissionsAuthorizationFilter拦截,发现需要“user:list”权限
4、PermissionsAuthorizationFilter调用realm中的doGetAuthorizationInfo获取数据库中正确的权限
5、PermissionsAuthorizationFilter对user:list 和从realm中获取权限进行对比,如果“user:list”在realm返回的权限列表中,授权通过。
如果没有权限,就会跳转到一个没有权限访问的提示页面

1.10.3.创建/unauthorized.jsp
如果授权失败,跳转到/unauthorized.jsp 红色背景部分

<bean id="shiroFilter"
	class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	<!-- 注入安全管理器 -->
	<property name="securityManager" ref="securityManager" />

	<!-- 注入登录页面, 如果没有认证,会自动跳转到此页面进行认证 -->
	<property name="loginUrl" value="/login.do" />

	<!-- 注入认证成功页面 -->
	<property name="successUrl" value="/index.do" />


	<!-- 认证通过,没有权限访问跳转到的页面 -->
	<property name="unauthorizedUrl" value="/unauthorized.jsp" />
	<!-- 设置shiro的过滤器链 ,过滤器链的顺序从上到下执行 所有 一般 /**最好配置到最后面 -->
	<property name="filterChainDefinitions">
		<value>
			<!-- 放行今天资源 -->
			/images/**=anon
			/js/**=anon
			/css/**=anon
			
			/login.jsp = anon
			<!-- logout:退出登录过滤器,清除Session数据 -->
			/logout.do=logout
			<!-- /**所有请求 ,authc 表示所有请求都需要认证通过才可以访问 -->
			/** = authc
		</value>
	</property>
</bean>

1.10.3.1.问题总结
1、在spring-shiro.xml中配置过虑器链接,需要将全部的url和权限对应起来进行配置,实际开发项目中项目有很多权限配置,非常的麻烦(不建议使用)
(1)解决方案,使用注解配置
2、每次授权都需要调用realm查询数据库,对于系统性能有很大影响,可以通过shiro缓存来解决。
(1)解决方案,使用shiro的缓存技术-ehcache

1.10.4.支持注解配置授权
使用注解开发,首先在spring配置中开启shiro注解配置

在springmvc.xml中配置:

<!-- shiro为集成springMvc 拦截异常 -->
<bean
	class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	<property name="exceptionMappings">
		<props>
			<!-- 没有权限异常跳转的页面 -->
			<prop key="org.apache.shiro.authz.UnauthorizedException">/unauthorized.jsp</prop>
		</props>
	</property>
</bean>

<!-- 开启aop,对代理类 -->
<aop:config proxy-target-class="true"></aop:config>

<!-- 开启shiro的注解支持 -->
<bean
	class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
	<!-- 注入安全管理器 -->
	<property name="securityManager" ref="securityManager"></property>

1.10.5.在controller方法中添加注解

@Controller
@RequestMapping("/user")
public class UserController {
	
@RequestMapping("/list.do")
@RequiresPermissions("user:list")
public String list(HttpServletRequest req, Model model) {
	return "index";
}
@RequestMapping("/update.do")
@RequiresPermissions("user:updae")
public String update(HttpServletRequest req, Model model) {
	return "redirect:/user/list.do";
}
@RequestMapping("/delete.do")
@RequiresPermissions("user:delete")
public String delete(HttpServletRequest req, Model model) {
	return "redirect:/user/list.do";
}

}

1.10.6.jsp标签 授权
1.10.6.1.标签介绍
Jsp页面添加:
<%@ tagliburi=“http://shiro.apache.org/tags” prefix=“shiro” %>
在这里插入图片描述
1.10.6.2. index.jsp页面标签控制权限

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://shiro.apache.org/tags"  prefix="shiro"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
首页<br>
<a href="${pageContext.request.contextPath}/logout.do">退出登录</a>
<hr>
<!-- 判断是否有 user:list 权限,如果有,显示标签内部内容,没有不显示 -->
<shiro:hasPermission name="user:list">
	<a href="${pageContext.request.contextPath}/user/list.do">用户管理</a><br>
</shiro:hasPermission>

<shiro:hasPermission name="role:list">
	<a href="#">角色管理</a><br>
</shiro:hasPermission>
<shiro:hasPermission name="permission:list">
	<a href="#">权限管理</a><br>
</shiro:hasPermission>
</body>
</html>

1.10.7.授权测试
如果当前登录用户没有授权,用户的界面就不会显示对应的菜单
如果用户强制访问某一个没有授权的页面,那么会跳转到没有授权提示页面

1.11.shiro缓存
问题:为什么要有缓存?
答:因为认证通过以后访问的页面,每访问一次都要进行一次授权,都会执行一次授权方法,授权相关的权限数据都是从数据库查询的,会造成频繁的查询数据库,影响系统性能

所以:针对上边授权频繁查询数据库,需要使用shiro缓存技术。

1.11.1.缓存流程

shiro中提供了对认证信息和授权信息的缓存。shiro默认是关闭认证信息缓存的,对于授权信息的缓存shiro默认开启的。主要研究授权信息缓存,因为授权的数据量大。

前提:用户认证通过(登录成功)。
用户第一次授权:调用realm查询数据库
用户第二次授权:不调用realm查询数据库,直接从缓存中取出授权信息(权限标识符)。

1.11.2.使用ehcache
Shiro推荐使用 ehcache第三方缓存
添加Ehcache的依赖包

<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>1.2.3</version>
		</dependency>
		<dependency>
		    <groupId>net.sf.ehcache</groupId>
		    <artifactId>ehcache-core</artifactId>
		    <version>2.6.0</version>
		</dependency>

1.11.2.2.配置cacheManager

<!-- 配置安全管理器 -->
<bean id="securityManager"
	class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	<!-- 注入realm -->
	<property name="realm" ref="customRealm" />
	<!-- 注入缓存管理器 -->
	<property name="cacheManager" ref="cacheManager"></property>
</bean>
	<!-- 缓存管理器 -->
	<bean id="cacheManager"
		class="org.apache.shiro.cache.ehcache.EhCacheManager">
		<!-- 读取ehcache配置文件 -->
		<property name="cacheManagerConfigFile"
			value="classpath:shiro-ehcache.xml"></property>
</bean>

1.11.2.3.shiro-ehcache.xml
在 classpath 路径下面创建 ehcache缓存的配置文件

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
	<!--diskStore:缓存数据持久化的目录 地址  -->
	<diskStore path="D:\develop\ehcache" />
	<defaultCache 
		maxElementsInMemory="1000" 
		maxElementsOnDisk="10000000"
		eternal="false" 
		overflowToDisk="false" 
		diskPersistent="false"
		timeToIdleSeconds="120"
		timeToLiveSeconds="120" 
		diskExpiryThreadIntervalSeconds="120"
		memoryStoreEvictionPolicy="LRU">
	</defaultCache>
</ehcache>

1.12.Session会话管理器

和shiro整合后,使用shiro的session管理,shiro提供sessionDao操作 会话数据。

配置sessionManager

<!-- 安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="customRealm" />
		<property name="sessionManager" ref="sessionManager" />
	</bean>
<!-- 会话管理器 -->
<!-- Session管理器 -->
	<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
		<!-- 设置session的失效时长,单位毫秒 -->
		<property name="globalSessionTimeout" value="#{1000 * 3600 * 24 * 7}"></property>
		
		<!-- 删除失效的session -->
		<property name="deleteInvalidSessions" value="true"/>
	</bean>

1.13.记住我
Shiro框架认证成功以后,默认的信息是存储在Session中的,Session的缺点就是如果数据浏览器关闭,Session失效,下次必须再次登录。所以,Shiro提供了记住我的功能,记住我功能底层使用的Cookie技术
用户登陆选择“自动登陆”本次登陆成功会向cookie写身份信息,下次登陆从cookie中取出身份信息实现自动登陆。

1.13.1.用户身份实现java.io.Serializable接口
向cookie记录身份信息需要用户身份信息对象实现序列化接口,如下:

public class User  implements Serializable{

1.13.2.配置rememeberMeManager
使用记住我功能需要设置Shiro的rememberMeManage 管理器

<bean id="securityManager"
	class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	<!-- 注入realm -->
	<property name="realm" ref="comteRealm" />
	
	<!-- 缓存管理 -->
	<property name="cacheManager" ref="cacheManager"/>
	
	<!-- 会话管理 -->
	<property name="sessionManager" ref="sessionManager" />
	
	<!-- 记住我 -->
	<property name="rememberMeManager" ref="rememberMeManager"/>
	
</bean>

<!-- 记住我 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
	<!-- 注入cookie -->
	<property name="cookie">
		<bean class="org.apache.shiro.web.servlet.SimpleCookie">
			<!-- 使用构造器设置cookie名称 -->
			<constructor-arg value="rememberMe"/>
		
			<!-- 设置最大有效期 :单位秒 -->
			<property name="maxAge" value="#{3600 * 24 * 7}"/>
			
			<!-- 保存到本地Cookie的名称 -->
			<!-- <property name="name" value="rememberMe"/> -->
		</bean>
	</property>
	
</bean>

1.13.3.登陆页面
记住我的表单的name默认是 remeberMe

<form action="${pageContext.request.contextPath}/login.do" method="post">
账号:<input name="username"><br>
密码:<input name="password"><br>
记住我:<input type="checkbox" name="rememberMe">
<button type="submit">登录</button>
</form>

1.13.4.自定义FormAuthenticationFilter

表单认证 使用的是 org.apache.shiro.web.filter.authc.FormAuthenticationFilter 中对应
那么这个过滤器接受的认证参数都是有规则的
认证的身份(账号)默认叫做 username
认证的凭证(密码)默认叫做 password
认证的记住我 默认叫做 rememberMe
所以,在开发者编写的认证(登录)表单的对应的名称必须和默认保持一致
但是开发者也可以自定这些认证的表单名称规则
在这里插入图片描述但是开发者也可以自定义配置对应的名称

1.13.5.配置rememberMe的input名称

<bean id="formAuthenticationFilter" class="cn.zj.shiro.MyFormAuthenticationFilter">
	<!-- 设置表单提交的账号表单名称 -->
	<property name="usernameParam" value="username"/>
	<!-- 设置表单提交的账号表单名称 -->
	<property name="passwordParam" value="password"/>
	<!-- 设置表单提交的账号表单名称 -->
	<property name="rememberMeParam" value="rememberMe"/>
</bean>
<!-- web.xml 中配置的Filter对应的Bean -->
<bean id="shiroFilter"
	class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	<!-- 注入安全管理器 -->
	<property name="securityManager" ref="securityManager" />

	<!-- 注入登录页面, 如果没有认证,会自动跳转到此页面进行认证 -->
	<property name="loginUrl" value="/login.do" />

	<!-- 注入认证成功页面 -->
	<property name="successUrl" value="/index.do" />
	
	<!-- 自定义Filter -->
	<property name="filters">
		<map>
			<!-- 使用自定义的表单认证过滤器-->
			<entry key="authc" value-ref="formAuthenticationFilter"></entry>
		</map>
	</property>

	<!-- 认证通过,没有权限访问跳转到的页面 -->
	<property name="unauthorizedUrl" value="/unauthorized.jsp" />
	<!-- 设置shiro的过滤器链 ,过滤器链的顺序从上到下执行 所有 一般 /**最好配置到最后面 -->
	<property name="filterChainDefinitions">
		<value>
			<!-- 放行今天资源 -->
			/images/**=anon
			/js/**=anon
			/css/**=anon

			/login.jsp = anon
			<!-- logout:退出登录过滤器,清除Session数据 -->
			/logout.do=logout
			
			<!-- 配置记住我访问的页面 -->
			/index.do=user
			
			<!-- /**所有请求 ,authc 表示所有请求都需要认证通过才可以访问 -->
			/** = authc
		</value>
	</property>
</bean>

1.13.7.使用UserFilter
如果设置记住我,下次访问某些url时可以不用登陆。将记住我即可访问的地址配置让UserFilter拦截。

<!-- 配置记住我访问的页面 -->
				/index.do=user
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值