聊聊Springboot2.x的session和cookie有效期
Springboot2.x的session和cookie有效期
session和cookie的相關(guān)區(qū)別和聯(lián)系就不介紹了,這里就記錄一下筆記。
背景
最近在做單點(diǎn)登錄CAS的問題,在后端塞一個(gè)cookie uid用于前端的登錄拉起,并且設(shè)置了max-age, 但是測試的時(shí)候,一直有個(gè)問題,就是前端頁面打開,不做任何操作,停留30分鐘左右,然后點(diǎn)擊按鈕,按理說是應(yīng)該會(huì)發(fā)送到后端,但是實(shí)際上卻發(fā)生了302的跳轉(zhuǎn),前端也沒有拉起登錄頁面,說明登錄狀態(tài)還在(根據(jù)uid判斷),但是為什么后端日志沒有打????
也就是說,頁面半小時(shí)左右沒做任何操作,這個(gè)按鈕就跳出了前端和后端,失去了控制,百思不得其解啊。
經(jīng)過一番排查,終于發(fā)現(xiàn)問題了,前端的登錄態(tài)判斷條件,uid是后端塞進(jìn)去的,并且設(shè)置了max-age為1小時(shí),但是項(xiàng)目里的springboot2.x,并沒有配置下面內(nèi)容:
server.servlet.session.timeout= # session的有效期,默認(rèn)為30min server.servlet.session.cookie.max-age= #cookie的有效期,默認(rèn)為-1 即是和瀏覽器關(guān)閉狀態(tài)有關(guān)
后來測試了一番,在代碼里add cookie和 server.servlet.session.cookie.max-age 之間的參數(shù)比較
public int test(HttpServletRequest request, HttpServletResponse response) { int maxInactiveInterval = request.getSession().getMaxInactiveInterval(); Cookie[] cookies = request.getCookies(); System.out.println("maxInactiveInterval: " + maxInactiveInterval); Cookie cookie = new Cookie("uid","koo"); cookie.setMaxAge(5); response.addCookie(cookie); return maxInactiveInterval; }
測試策略為:
設(shè)置server.servlet.session.cookie.max-age 和 cookie.setMaxAge(5);的值不一樣,然后在瀏覽器查看。
最后的結(jié)論是:
server.servlet.session.cookie.max-age控制的是JESSIONID的有效期,Cookie cookie = new Cookie(“uid”,“koo”); cookie.setMaxAge(5);這種方式的cookie 特定字段的有效期是分開的。
另外一個(gè)配置:
server.servlet.session.timeout表示的是session的有效期,查看源代碼默認(rèn)值為:30min,或者也可以這樣輸出session的有效期:int maxInactiveInterval = request.getSession().getMaxInactiveInterval();
項(xiàng)目問題解釋
我在項(xiàng)目里只有Cookie cookie = new Cookie(“uid”,“koo”); cookie.setMaxAge(3600); 并且是設(shè)置為3600秒的有效期,但是服務(wù)器的session有效期server.servlet.session.timeout是沒有配置的,所以前端登錄態(tài)判斷的時(shí)候,uid是還存在的,所以發(fā)送請求的時(shí)候,不會(huì)拉起登錄頁面,會(huì)把請求發(fā)送出去,但是后端的session已經(jīng)過期了,導(dǎo)致發(fā)生302的請求,請求看起來失去了控制。
最后解決辦法為
server.servlet.session.timeout=86400 server.servlet.session.cookie.max-age=86400 Cookie cookie = new Cookie(“uid”,“koo”); cookie.setMaxAge(23*3600); response.addCookie(cookie);
登錄態(tài)字段的cookie有效期要小于session的有效期,這樣就會(huì)在先于發(fā)送請求的時(shí)候,拉起登錄頁面了,不會(huì)再出現(xiàn)失去控制的情況。
升級springboot 2.x 踩過的坑——跨域?qū)е聅ession問題
目前IT界主流前后端分離,但是在分離過程中一定會(huì)存在跨域的問題。
什么是跨域?
是指瀏覽器從一個(gè)域名的網(wǎng)頁去請求另一個(gè)域名的資源時(shí),域名、端口、協(xié)議任一不同,都是跨域?! ?/p>
做過web后臺(tái)的童鞋都知道,跨域這種問題是比較常見的,最近我們公司需要將springboot 1.x升級到2.x,在升級之后遇到了挺多的問題,例如某些類過時(shí)了或者某些類找不到等,還有就是今天要說得session不一致的情況(eg:請求不同接口,sessionID都不一致,即session不會(huì)共享)。
場景
今天前端童鞋跟我說,本地環(huán)境調(diào)用校驗(yàn)驗(yàn)證碼接口一直報(bào)“未獲取到用戶信息,請重新登錄”,我直接看了下這個(gè)接口,他是從session中獲取的用戶信息,如果用戶不存在則會(huì)拋這種提示語。
HttpSession session = request.getSession(false); Object sessionObj = session.getAttribute(LOGIN_NAME);//session為空 String currentName = null == sessionObj ? null : sessionObj.toString(); if (StringUtils.isBlank(currentName)) { res.setMessage(messageUtil.getMessage("reLogin")); res.setStatusCode(StatusCode.RE_LOGIN.getCode()); return res; }
因?yàn)槲覀兊卿浐托r?yàn)驗(yàn)證碼是兩個(gè)接口,所以用戶信息是從登錄放進(jìn)去的,然后在驗(yàn)證碼接口中獲取用戶信息做后面的進(jìn)一步操作?! ?/p>
看到這個(gè)之后,我看了下springboot的配置,都有配置session 共享的配置,而且我的session是放在redis里面的,有點(diǎn)郁悶,然后我就登錄到測試環(huán)境登錄一下試試看,咦~~居然可以,最后才反應(yīng)過來是跨域的問題,然后我又去看了下代碼,是有配置跨域的問題,真奇怪!
經(jīng)過一天的百度與排查,我回滾到springboot 1.x居然沒有這個(gè)問題,才定位到是升級到springboot 2.x導(dǎo)致的原因,好了,已經(jīng)抓住兇手了,這下子好對癥下藥了,去網(wǎng)上看了 springboot升級到2.xspring session 相關(guān)的問題?! ?/p>
終于發(fā)現(xiàn)了新大陸,spring-session 2.x 中 Cookie里面居然引入了SameSite 這個(gè)叼毛,他默認(rèn)值是 Lax,好了咱們來看看這個(gè)是什么東西?
SameSite Cookie 是用來防止CSRF攻擊,它有兩個(gè)值:Strict、Lax
- SameSite = Strict:
意為嚴(yán)格模式,表明這個(gè)cookie在任何情況下都不可能作為第三方cookie;
- SameSite = Lax:
意為寬松模式,在get請求是可以作為第三方cookie,但是不能攜帶cookie進(jìn)行跨域post訪問(這就很蛋疼了,我們那個(gè)校驗(yàn)接口就是POST請求)
總結(jié)
前端請求到后臺(tái),每次session都不一樣,每次都是新的會(huì)話,導(dǎo)致獲取不到用戶信息
解決方案
將SameSite設(shè)置為空
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.session.web.http.CookieSerializer; import org.springframework.session.web.http.DefaultCookieSerializer; @Configuration public class SpringSessionConfig { public SpringSessionConfig() { } @Bean public CookieSerializer httpSessionIdResolver() { DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); // 取消僅限同一站點(diǎn)設(shè)置 cookieSerializer.setSameSite(null); return cookieSerializer; } }
pom.xml依賴
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-core</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> <version>1.3.1.RELEASE</version> </dependency>
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
微服務(wù)之間如何通過feign調(diào)用接口上傳文件
這篇文章主要介紹了微服務(wù)之間如何通過feign調(diào)用接口上傳文件的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Java使用雪花算法生成唯一ID的實(shí)現(xiàn)示例
雪花算法是 Twitter 開源的一種分布式ID生成算法,其目的是生成全局唯一的 ID,本文主要介紹了Java使用雪花算法生成唯一ID的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07SpringMVC Tomcat控制臺(tái)亂碼問題解決方案
這篇文章主要介紹了SpringMVC Tomcat控制臺(tái)亂碼問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05Java 處理超大數(shù)類型之BigInteger案例詳解
這篇文章主要介紹了Java 處理超大數(shù)類型之BigInteger案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09