Spring security开启remember me功能,配置session超时,导致csrf验证失败

本文主要是介绍Spring security开启remember me功能,配置session超时,导致csrf验证失败,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

概述

当开启remember me功能,且配置session超时,当session超时后,会清空session,刷新页面可以正常实现记住我的功能,但是存放到session中的csrf token已被清空,会提示csrf校验异常,跳转到登录页面,导致remember me功能无法实现。

配置remember me + session超时

后端

public class HttpSecurityConfigurer {@Overridepublic void configure(HttpSecurity http) throws Exception {http//....anyRequest().authenticated().and().rememberMe().tokenValiditySeconds(86400)//...}
}
# resources/config/application-dev.yml
server:port: 8080servlet:session:timeout: 80s # 超时时间80s

5.2.2前端

登录的URL中增加 remember-me请求参数

&remember-me=${encodeURIComponent(data['remember-me'])}`;

解决方案

移动端无法读取cookie中的csrf的token增加到请求的header中,可以使用本解决方案。

只有在用户登录成功后,才生成csrf的token增加到cookie中,并且将csrf的token增加到用户响应信息中。前端发起请求的时候,从用户信息中获取csrf的token,增加到请求的header中。

5.4.2.后端

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import com.fasterxml.jackson.databind.ObjectMapper;/*** 登录成功后保持token** */
public class AjaxAuthenticationSuccessCustomizerHandler extends AjaxAuthenticationSuccessHandler {private ObjectMapper mapper;private CsrfTokenRepository csrfTokenRepository;private OnAuthenticationSuccessResponseProvider successResponseProvider;public AjaxAuthenticationSuccessCustomizerHandler(ObjectMapper mapper,OnAuthenticationSuccessResponseProvider successResponseProvider) {super(mapper, successResponseProvider);}public AjaxAuthenticationSuccessCustomizerHandler(ObjectMapper mapper,OnAuthenticationSuccessResponseProvider successResponseProvider,CsrfTokenRepository csrfTokenRepository) {super(mapper, successResponseProvider);this.mapper = mapper;this.successResponseProvider = successResponseProvider;this.csrfTokenRepository = csrfTokenRepository;}@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,Authentication authentication)throws IOException, ServletException {response.setStatus(HttpServletResponse.SC_CREATED);// 用户响应信息设置TOKENclearAuthenticationAttributes(request);}private String generateToken(HttpServletRequest request, HttpServletResponse response) {CsrfTokenCustomizer newToken = (CsrfTokenCustomizer) csrfTokenRepository.generateToken(request);newToken.setCanSave(true);csrfTokenRepository.saveToken(newToken, request, response);request.setAttribute(CsrfToken.class.getName(), newToken);request.setAttribute(newToken.getParameterName(), newToken);return newToken.getToken();}
}
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.security.core.Authentication;
import org.springframework.security.web.csrf.CsrfTokenRepository;/*** 删除csrfToken**/
public class AjaxLogoutSuccessCustomizerHandler extends AjaxLogoutSuccessHandler {private CsrfTokenRepository csrfTokenRepository;public AjaxLogoutSuccessCustomizerHandler(CsrfTokenRepository csrfTokenRepository) {this.csrfTokenRepository = csrfTokenRepository;}@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,Authentication authentication)throws IOException, ServletException {if (csrfTokenRepository instanceof CookieCsrfTokenCustomizerRepository) {CookieCsrfTokenCustomizerRepository repositoryCustomizer = (CookieCsrfTokenCustomizerRepository) csrfTokenRepository;repositoryCustomizer.clearToken(null, request, response);}super.onLogoutSuccess(request, response, authentication);}
}
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;/*** 根据Token中标识判断是否可以保持** */
public class CookieCsrfTokenCustomizerRepository implements CsrfTokenRepository {private CsrfTokenRepository cookieCsrfTokenRepository;public CookieCsrfTokenCustomizerRepository(CookieCsrfTokenRepository cookieCsrfTokenRepository) {this.cookieCsrfTokenRepository = cookieCsrfTokenRepository;}@Overridepublic CsrfToken generateToken(HttpServletRequest request) {CsrfToken csrfToken = cookieCsrfTokenRepository.generateToken(request);return new CsrfTokenCustomizer(csrfToken);}@Overridepublic void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {if (token == null) {return;}if (token instanceof CsrfTokenCustomizer) {CsrfTokenCustomizer myCsrfToken = (CsrfTokenCustomizer) token;if (!myCsrfToken.isCanSave()) {return;}}cookieCsrfTokenRepository.saveToken(token, request, response);}public void clearToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {cookieCsrfTokenRepository.saveToken(token, request, response);}@Overridepublic CsrfToken loadToken(HttpServletRequest request) {return cookieCsrfTokenRepository.loadToken(request);}
}
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import com.fasterxml.jackson.databind.ObjectMapper;/*** csrf的配置**/
@Configuration
public class CsrfCustomizerConfiguration {@Beanpublic CsrfTokenRepository csrfTokenRepository() {CookieCsrfTokenRepository cookieCsrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();cookieCsrfTokenRepository.setHeaderName("X-CSRF-TOKEN");cookieCsrfTokenRepository.setCookiePath("/");return new CookieCsrfTokenCustomizerRepository(cookieCsrfTokenRepository);}
}
import org.springframework.security.web.csrf.CsrfToken;/*** 增加能否保持的标志** */
public class CsrfTokenCustomizer implements CsrfToken {private final CsrfToken csrfToken;private boolean canSave = false;public CsrfTokenCustomizer(CsrfToken csrfToken) {this.csrfToken = csrfToken;}@Overridepublic String getHeaderName() {return this.csrfToken.getHeaderName();}@Overridepublic String getParameterName() {return this.csrfToken.getParameterName();}@Overridepublic String getToken() {return this.csrfToken.getToken();}public boolean isCanSave() {return canSave;}public void setCanSave(boolean canSave) {this.canSave = canSave;}
}

public class HttpSecurityConfigurer {//...private final CsrfTokenRepository csrfTokenRepository;public HttpSecurityConfigurer(//...CsrfTokenRepository csrfTokenRepository) {//...this.csrfTokenRepository = csrfTokenRepository;}@Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf()//  ....csrfTokenRepository(csrfTokenRepository)//  ...}
}

这篇关于Spring security开启remember me功能,配置session超时,导致csrf验证失败的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/567425

相关文章

解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题

《解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题》本文主要讲述了在使用MyBatis和MyBatis-Plus时遇到的绑定异常... 目录myBATis-plus-boot-starpythonter与mybatis-spring-b

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

python实现自动登录12306自动抢票功能

《python实现自动登录12306自动抢票功能》随着互联网技术的发展,越来越多的人选择通过网络平台购票,特别是在中国,12306作为官方火车票预订平台,承担了巨大的访问量,对于热门线路或者节假日出行... 目录一、遇到的问题?二、改进三、进阶–展望总结一、遇到的问题?1.url-正确的表头:就是首先ur

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

javafx 如何将项目打包为 Windows 的可执行文件exe

《javafx如何将项目打包为Windows的可执行文件exe》文章介绍了三种将JavaFX项目打包为.exe文件的方法:方法1使用jpackage(适用于JDK14及以上版本),方法2使用La... 目录方法 1:使用 jpackage(适用于 JDK 14 及更高版本)方法 2:使用 Launch4j(

JAVA利用顺序表实现“杨辉三角”的思路及代码示例

《JAVA利用顺序表实现“杨辉三角”的思路及代码示例》杨辉三角形是中国古代数学的杰出研究成果之一,是我国北宋数学家贾宪于1050年首先发现并使用的,:本文主要介绍JAVA利用顺序表实现杨辉三角的思... 目录一:“杨辉三角”题目链接二:题解代码:三:题解思路:总结一:“杨辉三角”题目链接题目链接:点击这里

SpringBoot使用注解集成Redis缓存的示例代码

《SpringBoot使用注解集成Redis缓存的示例代码》:本文主要介绍在SpringBoot中使用注解集成Redis缓存的步骤,包括添加依赖、创建相关配置类、需要缓存数据的类(Tes... 目录一、创建 Caching 配置类二、创建需要缓存数据的类三、测试方法Spring Boot 熟悉后,集成一个外

使用JavaScript操作本地存储

《使用JavaScript操作本地存储》这篇文章主要为大家详细介绍了JavaScript中操作本地存储的相关知识,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录本地存储:localStorage 和 sessionStorage基本使用方法1. localStorage