1.shiro 提供记住我的功能,当将form表单中name="rememberMe" 的value设为true或者登陆的token中。token.setRememberMe(true) 的时候,用户关闭浏览器之后,现在进入需要认证的资源的时候就不需要再登陆。

2.form表单中的value不仅仅只有true 的状态位,还可以设置t、1、enabled、y、yes、on这集中状态位都表示记住我。

3.登陆页面login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<form action="/shiro/doLogin" >
<table>
<tr>
<td>用户名:</td>
<td><input type="text" value="" name="loginName"></td>
</tr>
<tr>
<td>用户名:</td>
<td><input type="password" value="" name="password"></td>
</tr>
<%--记住我功能--%>
<tr>
<td>
<%--这里为了方便我默认将value设置为true,shiro对value 的判断除了true这个状态位还有:t,1,enabled,y,yes,on这几种--%>
<input type="checkbox" value="true" name="rememberMe">
</td>
<td>记住我</td>
</tr>
</table>
<input type="submit" value="登录">
</form>
</body>
</html>

4.spring 配置rememberMe

  

      <!--rememberMe cookie-->
<bean id="rememberMe" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe"></constructor-arg>
<property name="httpOnly" value="true"></property>
<!--cookie 的最大失效时间 30天-->
<property name="maxAge" value="259200"></property>
</bean>

maxAge=-1 表示关闭浏览器cookie失效

 <!--rememberMe 管理器-->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"></property>
<property name="cookie" ref="rememberMe"></property>
</bean>
cipherKey:表示设置cookie的加密算法,采用的是base64的加密
<!--form表单验证的过滤器-->
<bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
<!--loginName 对应form表单的用户名-->
<property name="usernameParam" value="loginName" />
<!--password 对应form表单的密码-->
<property name="passwordParam" value="password" />
<!--rememberMe 记住我checkbox 是否记住我默认为false-->
<property name="rememberMeParam" value="rememberMe" />
<!--form 的action-->
<property name="loginUrl" value="/shiro/doLogin" />
</bean>

form表单登陆的过滤器,这个过滤器对应的认证key是authc,当登陆的请求匹配到这个key的时候,就将这个过滤器加入到当前请求的过滤器链中。

   <!--指定shiro的核心管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--可以设置一个或者多个安全域-->
<property name="realm" ref="customRealm" />
<!-- 会话管理 -->
<property name="sessionManager" ref="sessionManager" />
<!--记住我-->
<property name="rememberMeManager" ref="rememberMeManager"/>
</bean>

将rememberMe的管理器交给securityManager 管理。

  <!-- Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行 -->
<!-- Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持 -->
<!--ShiroFilterFactoryBean 是一个shiroFilter的工厂类,负责实例化过滤器-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager"/>
<!-- 要求登录时的链接,当request请求被解析为需要认证则跳转到这个链接进行登录 -->
<property name="loginUrl" value="/shiro/goLogin"/>
<!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码为main.jsp了) -->
<!-- <property name="successUrl" value="/system/main"/> -->
<!-- 用户访问未对其授权的资源时,所显示的连接 -->
<!-- 若想更明显的测试此属性可以修改它的值,如unauthor.jsp,然后用[玄玉]登录后访问/admin/listUser.jsp就看见浏览器会显示unauthor.jsp -->
<property name="unauthorizedUrl" value="/"/>
<!-- Shiro连接约束配置,即过滤链的定义 -->
<!-- 此处可配合这篇文章来理解各个过滤连的作用http://blog.csdn.net/jadyer/article/details/12172839 -->
<!-- 下面value值的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的 -->
<!--shiro的默认过滤器分为两种:认证过滤器:anon,authcBasic,auchc,user 和授权过滤器:perms,roles,ssl,rest,port-->
<!-- anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种 -->
<!-- authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter -->
<!-- user: 表示身份验证通过,或者记住我-->
<!-- rememberMe:记住我设置后不用再需要登录-->
<property name="filterChainDefinitions">
<value>
<!--配置记住我拦截-->
/shiro/userInfo=user
<!-- /mydemo/login=anon
/mydemo/getVerifyCodeImage=anon
/main**=authc
/user/info**=authc
/admin/listUser**=authc,perms[admin:manage]-->
</value>
</property>
</bean>

4.ShiroController.java

package com.xiao.core.shiro;

import com.alibaba.druid.sql.visitor.functions.Char;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; @Controller
@RequestMapping("/shiro")
@Scope("prototype")
public class ShiroController { //跳转到用户登录页面
@RequestMapping("/goLogin")
public ModelAndView goLogin(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("/user/login");
return modelAndView;
} //用户登录请求
@RequestMapping("/doLogin")
public ModelAndView doLogin(UserEntity userEntity){
ModelAndView modelAndView=new ModelAndView();
String loginName=userEntity.getLoginName();
String password=userEntity.getPassword();
//获取主题
Subject subject=SecurityUtils.getSubject(); //创建token
UsernamePasswordToken token=new UsernamePasswordToken();
token.setUsername(loginName);
token.setPassword(password.toCharArray()); //设置记住我
token.setRememberMe(true);
//开始登录
subject.login(token); //判断是否登录成功
if(subject.isAuthenticated()){
modelAndView.setViewName("/user/loginSuccess"); //登录成功
}else{
modelAndView.setViewName("/user/loginFailed"); //登录失败
}
return modelAndView;
} /*测试跳转到下一个页面是否能继续使用权限*/
@RequestMapping("/userInfo")
public ModelAndView goUserInfo(){
//获取用户的信息
UserEntity userEntity=(UserEntity) SecurityUtils.getSubject().getPrincipal();
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("/user/userInfo");
/*modelAndView.addObject("user",userEntity);*/
return modelAndView;
} }

UserEntity:用户实体类

6.启动server容器之后:

点击登陆之后,当登陆成功之后会调用DefaultSecurityManager的rememberMeSuccessfulLogin方法将记住我写入到cookie中

   protected void rememberMeSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject) {
RememberMeManager rmm = getRememberMeManager();
if (rmm != null) {
try {
rmm.onSuccessfulLogin(subject, token, info);
} catch (Exception e) {
if (log.isWarnEnabled()) {
String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName() +
"] threw an exception during onSuccessfulLogin. RememberMe services will not be " +
"performed for account [" + info + "].";
log.warn(msg, e);
}
}
} else {
if (log.isTraceEnabled()) {
log.trace("This " + getClass().getName() + " instance does not have a " +
"[" + RememberMeManager.class.getName() + "] instance configured. RememberMe services " +
"will not be performed for account [" + info + "].");
}
}
}

之后再调用RememberManager的onSuccessfulLogin方法

   public void onSuccessfulLogin(Subject subject, AuthenticationToken token, AuthenticationInfo info) {
//清除上一个subject主题
forgetIdentity(subject); //创建新的认证
if (isRememberMe(token)) {
rememberIdentity(subject, token, info);
} else {
if (log.isDebugEnabled()) {
log.debug("AuthenticationToken did not indicate RememberMe is requested. " +
"RememberMe functionality will not be executed for corresponding account.");
}
}
}

继续跟踪会到设置cookie 的方法

   protected void rememberSerializedIdentity(Subject subject, byte[] serialized) {

        if (!WebUtils.isHttp(subject)) {
if (log.isDebugEnabled()) {
String msg = "Subject argument is not an HTTP-aware instance. This is required to obtain a servlet " +
"request and response in order to set the rememberMe cookie. Returning immediately and " +
"ignoring rememberMe operation.";
log.debug(msg);
}
return;
} HttpServletRequest request = WebUtils.getHttpRequest(subject);
HttpServletResponse response = WebUtils.getHttpResponse(subject); //serialized 是princple经过序列化之后的数据,将序列话的数据base64位编码
String base64 = Base64.encodeToString(serialized); Cookie template = getCookie(); //the class attribute is really a template for the outgoing cookies
Cookie cookie = new SimpleCookie(template);
cookie.setValue(base64);
      //设置记住我的cookie
cookie.saveTo(request, response);
}

7.登陆成功的cookie

.

8.关闭浏览器,访问/shiro/userInfo 将可以直接访问,不会跳转到登录页面


spring 配置 shiro rememberMe的更多相关文章

  1. 使用Spring配置shiro时,自定义Realm中属性无法使用注解注入解决办法

    先来看问题    纠结了几个小时终于找到了问题所在,因为shiro的realm属于Filter,简单说就是初始化realm时,spring还未加载相关业务Bean,那么解决办法就是将springmvc ...

  2. spring整合shiro配置BUG,Tomcat启动不了:Error during artifact deployment. See server log for details

    现象 spring配置shiro权限控制之后,项目无法启动 [2019-08-09 09:00:35,800] Artifact export_web_manager:war exploded: Er ...

  3. spring下配置shiro

    1.web.xml中加入shiro的过滤器: <!-- Spring --> <!-- 配置Spring配置文件路径 --> <context-param> < ...

  4. 学习Spring Boot:(十三)配置 Shiro 权限认证

    经过前面学习 Apache Shiro ,现在结合 Spring Boot 使用在项目里,进行相关配置. 正文 添加依赖 在 pom.xml 文件中添加 shiro-spring 的依赖: <d ...

  5. spring与shiro配置详解

    1.加入shiro相关依赖的jar包 pom.xml部分内容如下: <dependency> <groupId>org.apache.shiro</groupId> ...

  6. 基于spring的shiro配置

    shiro是一个特别简单,易用的框架,在此记录一下shiro的使用配置. 首先,创建四张表:user  role  user_role  permission,分别为用户.角色.用户与角色关系表和权限 ...

  7. Maven配置Spring+Hibernate Shiro权限控制项目

    前言:在Eclipse中安装好Maven插件,然后创建一个Sample项目.在Eclipse中检出Shiro的官方演示样例.地址http://svn.apache.org/repos/asf/shir ...

  8. Spring整合Shiro做权限控制模块详细案例分析

    1.引入Shiro的Maven依赖 <!-- Spring 整合Shiro需要的依赖 --> <dependency> <groupId>org.apache.sh ...

  9. Spring整合Shiro并扩展使用EL表达式

    Shiro是一个轻量级的权限控制框架,应用非常广泛.本文的重点是介绍Spring整合Shiro,并通过扩展使用Spring的EL表达式,使@RequiresRoles等支持动态的参数.对Shiro的介 ...

随机推荐

  1. JavaScript语句-流程控制语句

    JavaScript定义了一组语句,语句通常用于执行一定的任务.语句可以很简单,也可以很复杂. 选择结构,可以在程序中创建交叉结构来指定程序流的可能方向.JavaScript中有四种选择结构: 1.单 ...

  2. flex集成IFrame,IFrame集成UnityWebPlayer直接通讯调用解决方式

    做Web开发一般是flex与JS交互,UnityWebPlayer与JS交互. 它们之间相互调用比較常见. /** * Flex调用Javascript函数 * @params functionNam ...

  3. vs2010中设置qt环境的智能识别方案

    Qt搭建请参考:Win7系统VS2010下搭建qt开发环境 搭建好之后,虽然可以编译过去,但是写代码时,编辑器无法识别,也没有智能提示,并且代码中都是红色的提示如下: 此时需要设置一下include路 ...

  4. 检查 统计 异常 通信 time_wait

    [root@hadoop1 conf]# netstat -n | grep -v 127.0.0.1 | grep -v :3306  | grep TIME_WAIT | sort -k 5n | ...

  5. UVA796 Critical Links —— 割边(桥)

    题目链接:https://vjudge.net/problem/UVA-796 In a computer network a link L, which interconnects two serv ...

  6. varint算法——本质上是牺牲最高位作为标识数据结束位,达到变长编码,说白了就是贪心的分割位

    varint算法,摘自:http://blog.csdn.net/liaoquesg/article/details/50897327 最近在看<大规模WEB服务开发技术>这本书中.书中提 ...

  7. zoj3777(状态压缩)

    题目阐述: 给定n个座位,n个人,每个人可以做n个位置中的任意一个,P[i][j]代表第i个人做第j个位置获得的分数,求有多少种排列方式使得获得的分数大于等于M. 这道题跟数位dp的思想很像,都是穷举 ...

  8. 从0开始学习Hadoop(1) 环境准备 Win7环境+VirtureBox+Ubuntu

    虚拟机:VirtureBox 3.18 下载地址: https://www.virtualbox.org/ 操作系统:Ubuntu  版本:ubuntu-15.04-desktop-amd64.iso ...

  9. UI:单例的写法

    单例设计模式 参考 UIApplication sharedApplocation 详细解释 :参考 通讯录的helper 类的读取本地plist 文件的时候,使用的单例单例的要点有三个:一个类只能有 ...

  10. Hibernate4 拦截器(Interceptor) 实现实体类增删改的日志记录

    转自:https://blog.csdn.net/he90227/article/details/44783099 开发应用程序的过程中,经常会对一些比较重要的数据修改都需要写日志.在实际工作的工程中 ...