SpringSecurityでセッションを制御する

1。概要

この記事では、SpringSecurityを使用してHTTPセッションを制御する方法について説明します

この制御は、セッションタイムアウトから、同時セッションおよびその他の高度なセキュリティ構成の有効化にまで及びます。

2.セッションはいつ作成されますか?

セッションが作成されるタイミングと、SpringSecurityがセッションと対話する方法を正確に制御できます。

  • 常に–セッションがまだ存在しない場合は、常にセッションが作成されます
  • ifRequired –セッションは必要な場合にのみ作成されますデフォルト
  • 決して–フレームワークはセッション自体を作成することはありませんが、すでに存在する場合はセッションを使用します
  • ステートレス SpringSecurityによってセッションが作成または使用されることはありません
...

Java構成:

@Override protected void configure(HttpSecurity http) throws Exception { http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) }

この構成は、アプリケーション全体ではなく、SpringSecurityの機能のみを制御することを理解することが非常に重要です。Spring Securityは、セッションを作成しないように指示した場合、セッションを作成しない可能性がありますが、アプリは作成できます。

デフォルトでは、Spring Securityは必要なときにセッションを作成します。これは、「ifRequired」です。

以下のために、よりステートレスなアプリケーション、「決して」オプションは、春のセキュリティ自体は任意のセッションを作成しないことを保証します。ただし、アプリケーションが作成した場合、SpringSecurityはそれを利用します。

最後に、最も厳密なセッション作成オプションである「ステートレス」は、アプリケーションがセッションをまったく作成しないことを保証します

これはSpring3.1で導入され、Spring Securityフィルターチェーンの一部(主にHttpSessionSecurityContextRepositorySessionManagementFilterRequestCacheFilterなどのセッション関連部分)を効果的にスキップします。

これらのより厳密な制御メカニズムは、Cookieが使用されないことを直接意味するため、すべての要求を再認証する必要があります。このステートレスアーキテクチャは、RESTAPIとそのステートレス制約とうまく連携します。また、基本認証やダイジェスト認証などの認証メカニズムでもうまく機能します。

3.フードの下で

-認証プロセスを実行する前に、春のセキュリティが要求間のセキュリティコンテキストを格納して責任をフィルタで実行されますSecurityContextPersistenceFilterを。コンテキストは、HTTPセッションをストレージとして使用する戦略(デフォルトではHttpSessionSecurityContextRepository)に従って保存されます。

厳密なcreate-session =” stateless”属性の場合、この戦略は別の戦略(NullSecurityContextRepository)に置き換えられ、コンテキストを維持するためにセッションが作成または使用されることはありません

4.同時セッション制御

すでに認証されているユーザーが再度認証を試みると、アプリケーションはいくつかの方法のいずれかでそのイベントを処理できます。ユーザーのアクティブなセッションを無効にして、新しいセッションでユーザーを再度認証するか、両方のセッションが同時に存在できるようにすることができます。

同時セッション制御サポートを有効にする最初のステップは、web.xmlに次のリスナーを追加することです。

  org.springframework.security.web.session.HttpSessionEventPublisher  

または、次のようにBeanとして定義します。

@Bean public HttpSessionEventPublisher httpSessionEventPublisher() { return new HttpSessionEventPublisher(); }

これは、セッションが破棄されたときにSpringSecurityセッションレジストリに確実に通知されるようにするために不可欠です。

同じユーザーに対して複数の同時セッションを許可するシナリオを有効にするには、 要素はXML構成で使用する必要があります。

または、Java構成を介して:

@Override protected void configure(HttpSecurity http) throws Exception { http.sessionManagement().maximumSessions(2) }

5.セッションタイムアウト

5.1。セッションタイムアウトの処理

セッションがタイムアウトした後、ユーザーが期限切れのセッションIDでリクエストを送信すると、名前空間を介して構成可能なURLにリダイレクトされます。

同様に、ユーザーが有効期限が切れていないが完全に無効なセッションIDでリクエストを送信した場合、それらも構成可能なURLにリダイレクトされます。

 ... 

対応するJava構成:

http.sessionManagement() .expiredUrl("/sessionExpired.html") .invalidSessionUrl("/invalidSession.html");

5.2。SpringBootでセッションタイムアウトを設定する

プロパティを使用して、組み込みサーバーのセッションタイムアウト値を簡単に構成できます。

server.servlet.session.timeout=15m

期間の単位を指定しない場合、Springはそれを秒と見なします。

簡単に言うと、この構成では、15分間操作がないと、セッションが期限切れになります。この期間の後のセッションは無効と見なされます。

Tomcatを使用するようにプロジェクトを構成した場合、セッションタイムアウトの精度は、最低1分で、分単位でしかサポートされないことに注意する必要があります。これは、たとえば170秒のタイムアウト値を指定すると、2分のタイムアウトになることを意味します。

Finally, it's important to mention that even though Spring Session supports a similar property for this purpose (spring.session.timeout), if that's not specified then the autoconfiguration will fallback to the value of the property we first mentioned.

6. Prevent Using URL Parameters for Session Tracking

Exposing session information in the URL is a growing security risk (from place 7 in 2007 to place 2 in 2013 on the OWASP Top 10 List).

Starting with Spring 3.0, the URL rewriting logic that would append the jsessionid to the URL can now be disabled by setting the disable-url-rewriting=”true” in the namespace.

Alternatively, starting with Servlet 3.0, the session tracking mechanism can also be configured in the web.xml:

 COOKIE 

And programmatically:

servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));

This chooses where to store the JSESSIONID – in the cookie or in a URL parameter.

7. Session Fixation Protection With Spring Security

The framework offers protection against typical Session Fixation attacks by configuring what happens to an existing session when the user tries to authenticate again:

 ...

The corresponding Java configuration:

http.sessionManagement() .sessionFixation().migrateSession()

By default, Spring Security has this protection enabled (“migrateSession“) – on authentication a new HTTP Session is created, the old one is invalidated and the attributes from the old session are copied over.

If this is not the desired behavior, two other options are available:

  • when “none” is set, the original session will not be invalidated
  • when “newSession” is set, a clean session will be created without any of the attributes from the old session being copied over

8. Secure Session Cookie

Next, we'll discuss how to secure our session cookie.

We can use the httpOnly and secure flags to secure our session cookie:

  • httpOnly: if true then browser script won't be able to access the cookie
  • secure: if true then the cookie will be sent only over HTTPS connection

We can set those flags for our session cookie in the web.xml:

 1  true true  

This configuration option is available since Java servlet 3. By default, http-only is true and secure is false.

Let's also have a look at the corresponding Java configuration:

public class MainWebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext sc) throws ServletException { // ... sc.getSessionCookieConfig().setHttpOnly(true); sc.getSessionCookieConfig().setSecure(true); } }

If we're using Spring Boot, we can set these flags in our application.properties:

server.servlet.session.cookie.http-only=true server.servlet.session.cookie.secure=true

Finally, we can also achieve this manually by using a 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. Working With the Session

9.1. Session Scoped Beans

A bean can be defined with session scope simply by using the @Scope annotation on beans declared in the web-Context:

@Component @Scope("session") public class Foo { .. }

Or with XML:

Then, the bean can simply be injected into another bean:

@Autowired private Foo theFoo;

And Spring will bind the new bean to the lifecycle of the HTTP Session.

9.2. Injecting the Raw Session into a Controller

The raw HTTP Session can also be injected directly into a Controller method:

@RequestMapping(..) public void fooMethod(HttpSession session) { session.setAttribute(Constants.FOO, new Foo()); //... Foo foo = (Foo) session.getAttribute(Constants.FOO); }

9.3. Obtaining the Raw Session

現在のHTTPセッションは、生のサーブレットAPIを介してプログラムで取得することもできます

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); HttpSession session= attr.getRequest().getSession(true); // true == allow create

10.結論

この記事では、SpringSecurityを使用したセッションの管理について説明しました。また、Spring Referenceには、セッション管理に関する非常に優れたFAQが含まれています。

いつものように、この記事で紹介するコードはGithubで入手できます。これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。