使用Spring Security控制會(huì)話的方法
1.概述
在本文中,我們將說(shuō)明Spring Security如何允許我們控制HTTP會(huì)話。此控件的范圍從會(huì)話超時(shí)到啟用并發(fā)會(huì)話和其他高級(jí)安全配置。
2.會(huì)話何時(shí)創(chuàng)建?
我們可以準(zhǔn)確控制會(huì)話何時(shí)創(chuàng)建以及Spring Security如何與之交互:
•always - 如果一個(gè)會(huì)話尚不存在,將始終創(chuàng)建一個(gè)會(huì)話
•ifRequired - 僅在需要時(shí)創(chuàng)建會(huì)話(默認(rèn))
•never - 框架永遠(yuǎn)不會(huì)創(chuàng)建會(huì)話本身,但如果它已經(jīng)存在,它將使用一個(gè)
•stateless - Spring Security不會(huì)創(chuàng)建或使用任何會(huì)話
<http create-session="ifRequired">...</http>
Java配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
}
了解此配置僅控制Spring Security的功能非常重要 - 而不是整個(gè)應(yīng)用程序。如果我們不指示Spring Security,可能無(wú)法創(chuàng)建會(huì)話,但我們的應(yīng)用程序可能會(huì)!
默認(rèn)情況下,Spring Security會(huì)在需要時(shí)創(chuàng)建會(huì)話 - 這是“ifRequired”。
對(duì)于更無(wú)狀態(tài)的應(yīng)用程序,“never”選項(xiàng)將確保Spring Security本身不會(huì)創(chuàng)建任何會(huì)話;但是,如果應(yīng)用程序創(chuàng)建了一個(gè),那么Spring Security將使用它。
最后,最嚴(yán)格的會(huì)話創(chuàng)建選項(xiàng) - “stateless” - 保證應(yīng)用程序根本不會(huì)創(chuàng)建任何會(huì)話。
這是在Spring 3.1中引入的,它將有效地跳過(guò)部分Spring Security過(guò)濾器鏈。主要是會(huì)話相關(guān)的部分,如
HttpSessionSecurityContextRepository,SessionManagementFilter,RequestCacheFilter。
這些更嚴(yán)格的控制機(jī)制直接暗示不使用cookie,所以每個(gè)請(qǐng)求都需要重新進(jìn)行身份驗(yàn)證。這種無(wú)狀態(tài)架構(gòu)適用于REST API及其無(wú)狀態(tài)約束。它們也適用于基本和摘要式身份驗(yàn)證等身份驗(yàn)證機(jī)制。
3. Under The Hood
在執(zhí)行身份驗(yàn)證過(guò)程之前,Spring Security將運(yùn)行一個(gè)負(fù)責(zé)在請(qǐng)求之間存儲(chǔ)安全上下文的過(guò)濾器-SecurityContextPersistenceFilter。上下文將根據(jù)策略存儲(chǔ) - 默認(rèn)情況下為HttpSessionSecurityContextRepository - 它使用HTTP會(huì)話作為存儲(chǔ)。對(duì)于strict create-session =“stateless”屬性,此策略將替換為另一個(gè) - NullSecurityContextRepository - 并且不會(huì)創(chuàng)建或使用會(huì)話來(lái)保留上下文。
4.并發(fā)會(huì)話控制
當(dāng)已經(jīng)過(guò)身份驗(yàn)證的用戶嘗試再次進(jìn)行身份驗(yàn)證時(shí),應(yīng)用程序可以通過(guò)以下幾種方式之一處理該事件。它可以使用戶的活動(dòng)會(huì)話無(wú)效,并使用新會(huì)話再次對(duì)用戶進(jìn)行身份驗(yàn)證,或者允許兩個(gè)會(huì)話同時(shí)存在。
啟用并發(fā)會(huì)話控制支持的第一步是在web.xml中添加以下偵聽(tīng)器:
<listener> <listener-class> org.springframework.security.web.session.HttpSessionEventPublisher </listener-class> </listener>
或者將其定義為Bean - 如下所示:
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
這對(duì)于確保在銷毀會(huì)話時(shí)通知Spring Security會(huì)話注冊(cè)表是至關(guān)重要。
要為同一用戶啟用允許多個(gè)并發(fā)會(huì)話的方案,應(yīng)在XML配置中使用元素:
<http ...>
<session-management>
<concurrency-control max-sessions="2" />
</session-management>
</http>
或者,通過(guò)Java配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().maximumSessions(2)
}
5.會(huì)話超時(shí)
會(huì)話超時(shí)后,如果用戶發(fā)送的會(huì)話ID已過(guò)期,則會(huì)將其重定向到可通過(guò)命名空間配置的URL:
<session-management> <concurrency-control expired-url="/sessionExpired.html" ... /> </session-management>
同樣,如果用戶發(fā)送的會(huì)話ID未過(guò)期但完全無(wú)效,則它們也會(huì)被重定向到可配置的URL:
<session-management invalid-session-url="/invalidSession.html"> ... </session-management>
相應(yīng)的Java配置:
http.sessionManagement()
.expiredUrl("/sessionExpired.html")
.invalidSessionUrl("/invalidSession.html");
6.防止使用URL參數(shù)進(jìn)行會(huì)話跟蹤
在URL中公開(kāi)會(huì)話信息的安全風(fēng)險(xiǎn)越來(lái)越大(從2007年的第7位到2013年在OWASP排行榜前10位的第2位)。
從Spring 3.0開(kāi)始,現(xiàn)在可以通過(guò)在命名空間中設(shè)置disable-url-rewriting =“true”來(lái)禁用將jsessionid附加到URL的URL重寫(xiě)邏輯。
或者,從Servlet 3.0開(kāi)始,也可以在web.xml中配置會(huì)話跟蹤機(jī)制:
<session-config> <tracking-mode>COOKIE</tracking-mode> </session-config>
編程方式
servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));
這將選擇存儲(chǔ)JSESSIONID的位置 - 在cookie或URL參數(shù)中。
7. Spring Security的會(huì)話固定保護(hù)
該框架通過(guò)配置在用戶已有會(huì)話的情況但嘗試再次進(jìn)行身份驗(yàn)證時(shí),提供了針對(duì)典型會(huì)話固定攻擊的保護(hù):
<session-management session-fixation-protection="migrateSession"> ...
相應(yīng)的Java配置:
http.sessionManagement() .sessionFixation().migrateSession()
默認(rèn)情況下,Spring Security啟用了此保護(hù)(“migrateSession”) - 在身份驗(yàn)證時(shí),會(huì)創(chuàng)建一個(gè)新的HTTP會(huì)話,舊的會(huì)話將失效,舊會(huì)話的屬性將被復(fù)制。
如果這不是所需的行為,則可以使用其他兩個(gè)選項(xiàng):
•設(shè)置“none”時(shí),原始會(huì)話不會(huì)失效
•設(shè)置“newSession”時(shí),將創(chuàng)建一個(gè)干凈的會(huì)話,而不會(huì)復(fù)制舊會(huì)話中的任何屬性
8.安全會(huì)話Cookie
接下來(lái),我們將討論如何保護(hù)會(huì)話cookie。
我們可以使用httpOnly和secure標(biāo)簽來(lái)保護(hù)我們的會(huì)話cookie:
•httpOnly:如果為true,那么瀏覽器腳本將無(wú)法訪問(wèn)cookie
•secure:如果為true,則cookie將僅通過(guò)HTTPS連接發(fā)送
我們可以在web.xml中為會(huì)話cookie設(shè)置這些標(biāo)志:
<session-config>
<session-timeout>1</session-timeout>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
</session-config>
從Java servlet 3開(kāi)始,此配置選項(xiàng)可用。默認(rèn)情況下,http-only為true且secure為false。
我們來(lái)看看相應(yīng)的Java配置:
public class MainWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext sc) throws ServletException {
// ...
sc.getSessionCookieConfig().setHttpOnly(true);
sc.getSessionCookieConfig().setSecure(true);
}
}
如果我們使用Spring Boot,我們可以在application.properties中設(shè)置這些標(biāo)志:
server.servlet.session.cookie.http-only=true server.servlet.session.cookie.secure=true
最后,我們還可以使用Filter手動(dòng)實(shí)現(xiàn)此目的:
public class SessionFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
Cookie[] allCookies = req.getCookies();
if (allCookies != null) {
Cookie session =
Arrays.stream(allCookies).filter(x -> x.getName().equals("JSESSIONID"))
.findFirst().orElse(null);
if (session != null) {
session.setHttpOnly(true);
session.setSecure(true);
res.addCookie(session);
}
}
chain.doFilter(req, res);
}
}
9.Session使用
9.1。 Session Scoped Beans
只需在web-Context中,使用@Scope注釋聲明的bean:
@Component
@Scope("session")
public class Foo { .. }
或者使用XML:
<bean id="foo" scope="session"/>
然后,bean可以簡(jiǎn)單地注入另一個(gè)bean:
@Autowired private Foo theFoo;
Spring會(huì)將新bean綁定到HTTP Session的生命周期。
9.2。將會(huì)話注入控制器
原始HTTP會(huì)話也可以直接注入Controller方法:
@RequestMapping(..)
public void fooMethod(HttpSession session) {
session.addAttribute(Constants.FOO, new Foo();
//...
Foo foo = (Foo) session.getAttribute(Constants.Foo);
}
9.3。獲取會(huì)話
當(dāng)前的HTTP Session也可以通過(guò)原始Servlet API以編程方式獲得:
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); HttpSession session= attr.getRequest().getSession(true); // true == allow create
10.總結(jié)
在本文中,我們討論了使用Spring Security管理Sessions。此外,Spring Reference包含一個(gè)非常好的會(huì)話管理常見(jiàn)問(wèn)題解答。
與往常一樣,本文中提供的代碼可以在Github上獲得。這是一個(gè)基于Maven的項(xiàng)目,因此它應(yīng)該很容易導(dǎo)入和運(yùn)行。
以上所述是小編給大家介紹的使用Spring Security控制會(huì)話的方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
Java的Struts框架中配置國(guó)際化的資源存儲(chǔ)的要點(diǎn)解析
這篇文章主要介紹了Java的Struts框架中配置國(guó)際化的資源存儲(chǔ)的要點(diǎn)解析,針對(duì)用戶所使用的語(yǔ)言來(lái)配置資源文件,需要的朋友可以參考下2016-04-04
從log4j切換到logback后項(xiàng)目無(wú)法啟動(dòng)的問(wèn)題及解決方法
這篇文章主要介紹了從log4j切換到logback后項(xiàng)目無(wú)法啟動(dòng)的問(wèn)題及解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01
Spring Boot中@value的常見(jiàn)用法及案例
@Value注解是Spring框架中強(qiáng)大且常用的注解之一,本文主要介紹了SpringBoot中@value的常見(jiàn)用法及案例,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09
解決maven?maven.compiler.source和maven.compiler.target的坑
這篇文章主要介紹了解決maven?maven.compiler.source和maven.compiler.target的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
java實(shí)現(xiàn)讀取jar包中配置文件的幾種方式
本文主要介紹了java實(shí)現(xiàn)讀取jar包中配置文件的幾種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
SpringBoot面試突擊之過(guò)濾器和攔截器區(qū)別詳解
過(guò)濾器(Filter)和攔截器(Interceptor)都是基于?AOP(Aspect?Oriented?Programming,面向切面編程)思想實(shí)現(xiàn)的,用來(lái)解決項(xiàng)目中某一類問(wèn)題的兩種“工具”,但二者有著明顯的差距,接下來(lái)我們一起來(lái)看2022-10-10
Elasticsearch?Recovery索引分片分配詳解
這篇文章主要為大家介紹了關(guān)于Elasticsearch的Recovery索引分片分配詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2022-04-04
Java中使用HashMap時(shí)指定初始化容量性能解析
這篇文章主要為大家介紹了Java中使用HashMap時(shí)指定初始化容量性能解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02

