您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關如何使用Spring Security控制會話的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
1.概述
在本文中,我們將說明Spring Security如何允許我們控制HTTP會話。此控件的范圍從會話超時到啟用并發會話和其他高級安全配置。
2.會話何時創建?
我們可以準確控制會話何時創建以及Spring Security如何與之交互:
?always - 如果一個會話尚不存在,將始終創建一個會話
?ifRequired - 僅在需要時創建會話(默認)
?never - 框架永遠不會創建會話本身,但如果它已經存在,它將使用一個
?stateless - Spring Security不會創建或使用任何會話
<http create-session="ifRequired">...</http>
Java配置:
@Override protected void configure(HttpSecurity http) throws Exception { http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) }
了解此配置僅控制Spring Security的功能非常重要 - 而不是整個應用程序。如果我們不指示Spring Security,可能無法創建會話,但我們的應用程序可能會!
默認情況下,Spring Security會在需要時創建會話 - 這是“ifRequired”。
對于更無狀態的應用程序,“never”選項將確保Spring Security本身不會創建任何會話;但是,如果應用程序創建了一個,那么Spring Security將使用它。
最后,最嚴格的會話創建選項 - “stateless” - 保證應用程序根本不會創建任何會話。
這是在Spring 3.1中引入的,它將有效地跳過部分Spring Security過濾器鏈。主要是會話相關的部分,如
HttpSessionSecurityContextRepository,SessionManagementFilter,RequestCacheFilter。
這些更嚴格的控制機制直接暗示不使用cookie,所以每個請求都需要重新進行身份驗證。這種無狀態架構適用于REST API及其無狀態約束。它們也適用于基本和摘要式身份驗證等身份驗證機制。
3. Under The Hood
在執行身份驗證過程之前,Spring Security將運行一個負責在請求之間存儲安全上下文的過濾器-SecurityContextPersistenceFilter。上下文將根據策略存儲 - 默認情況下為HttpSessionSecurityContextRepository
- 它使用HTTP會話作為存儲。對于strict create-session =“stateless”
屬性,此策略將替換為另一個 - NullSecurityContextRepository - 并且不會創建或使用會話來保留上下文。
4.并發會話控制
當已經過身份驗證的用戶嘗試再次進行身份驗證時,應用程序可以通過以下幾種方式之一處理該事件。它可以使用戶的活動會話無效,并使用新會話再次對用戶進行身份驗證,或者允許兩個會話同時存在。
啟用并發會話控制支持的第一步是在web.xml中添加以下偵聽器:
<listener> <listener-class> org.springframework.security.web.session.HttpSessionEventPublisher </listener-class> </listener>
或者將其定義為Bean - 如下所示:
@Bean public HttpSessionEventPublisher httpSessionEventPublisher() { return new HttpSessionEventPublisher(); }
這對于確保在銷毀會話時通知Spring Security會話注冊表是至關重要。
要為同一用戶啟用允許多個并發會話的方案,應在XML配置中使用元素:
<http ...> <session-management> <concurrency-control max-sessions="2" /> </session-management> </http>
或者,通過Java配置:
@Override protected void configure(HttpSecurity http) throws Exception { http.sessionManagement().maximumSessions(2) }
5.會話超時
會話超時后,如果用戶發送的會話ID已過期,則會將其重定向到可通過命名空間配置的URL:
<session-management> <concurrency-control expired-url="/sessionExpired.html" ... /> </session-management>
同樣,如果用戶發送的會話ID未過期但完全無效,則它們也會被重定向到可配置的URL:
<session-management invalid-session-url="/invalidSession.html"> ... </session-management>
相應的Java配置:
http.sessionManagement() .expiredUrl("/sessionExpired.html") .invalidSessionUrl("/invalidSession.html");
6.防止使用URL參數進行會話跟蹤
在URL中公開會話信息的安全風險越來越大(從2007年的第7位到2013年在OWASP排行榜前10位的第2位)。
從Spring 3.0開始,現在可以通過在命名空間中設置disable-url-rewriting =“true”來禁用將jsessionid附加到URL的URL重寫邏輯。
或者,從Servlet 3.0開始,也可以在web.xml中配置會話跟蹤機制:
<session-config> <tracking-mode>COOKIE</tracking-mode> </session-config>
編程方式
servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));
這將選擇存儲JSESSIONID的位置 - 在cookie或URL參數中。
7. Spring Security的會話固定保護
該框架通過配置在用戶已有會話的情況但嘗試再次進行身份驗證時,提供了針對典型會話固定攻擊的保護:
<session-management session-fixation-protection="migrateSession"> ...
相應的Java配置:
http.sessionManagement() .sessionFixation().migrateSession()
默認情況下,Spring Security啟用了此保護(“migrateSession”) - 在身份驗證時,會創建一個新的HTTP會話,舊的會話將失效,舊會話的屬性將被復制。
如果這不是所需的行為,則可以使用其他兩個選項:
?設置“none”時,原始會話不會失效
?設置“newSession”時,將創建一個干凈的會話,而不會復制舊會話中的任何屬性
8.安全會話Cookie
接下來,我們將討論如何保護會話cookie。
我們可以使用httpOnly和secure標簽來保護我們的會話cookie:
?httpOnly:如果為true,那么瀏覽器腳本將無法訪問cookie
?secure:如果為true,則cookie將僅通過HTTPS連接發送
我們可以在web.xml中為會話cookie設置這些標志:
<session-config> <session-timeout>1</session-timeout> <cookie-config> <http-only>true</http-only> <secure>true</secure> </cookie-config> </session-config>
從Java servlet 3開始,此配置選項可用。默認情況下,http-only為true且secure為false。
我們來看看相應的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中設置這些標志:
server.servlet.session.cookie.http-only=true server.servlet.session.cookie.secure=true
最后,我們還可以使用Filter手動實現此目的:
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可以簡單地注入另一個bean:
@Autowired private Foo theFoo;
Spring會將新bean綁定到HTTP Session的生命周期。
9.2。將會話注入控制器
原始HTTP會話也可以直接注入Controller方法:
@RequestMapping(..) public void fooMethod(HttpSession session) { session.addAttribute(Constants.FOO, new Foo(); //... Foo foo = (Foo) session.getAttribute(Constants.Foo); }
9.3。獲取會話
當前的HTTP Session也可以通過原始Servlet API以編程方式獲得:
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); HttpSession session= attr.getRequest().getSession(true); // true == allow create
感謝各位的閱讀!關于“如何使用Spring Security控制會話”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。