私は現在、Spring Securityで保護されているSpring Boot Webアプリケーション(2.3.1ですが、次の問題もバージョン2.1.7および2.1.5で確認されています)を構築しています。私は主にデフォルト設定を使用します(例:埋め込みTomcat、埋め込みH2データベース、Spring Web-MVC)。POST
次のコードを使用して、寛容なマッピングでカスタム認証を行います。
UsernamePasswordAuthenticationToken authentication = ...;
SecurityContext context = SecurityContextHolder.getContext();
context.setAuthentication(authentication);
これは正常に動作します。学生の試験に使用したいので、認証を維持してセッションを維持したいので、サーバーソフトウェアが何らかの理由でクラッシュまたはダウンした場合でも、サーバーが再起動したときに再認証する必要はありません。
これにはSpring Session JDBCを使用しました。私は次の依存関係をmyに追加しましたpom.xml
:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
</dependency>
私への次の行 application.properties
spring.session.store-type=jdbc
ローカルでテストすると、これはすべて正常に機能します。データベースにセッションが表示されるのを確認して、すべてがうまくいきます。ただし、実際には、アプリケーションは次から開始されますiframe
。学習管理システムはLTI起動を実行します。これは、応答がで終了するPOSTリクエストですiframe
。テスト展開を行おうとする403
と、リクエストが認証されていないというエラーが発生しました。イライラするデバッグの1日の後、最終的にこの問題を突き止めることができましspring-session-jdbc
た。プロジェクトに追加すると、Webアプリケーションがのリクエストごとに新しいセッションID Cookieを送信するという事実に突き止められましたiframe
。なしで同じリクエストを繰り返すiframe
と、同じアプリケーションが正常に動作します。spring-session-jdbc
依存関係を削除すると、アプリケーションiframe
も内で正常に動作します。
iframe内で認証を実行すると、Spring Securityデバッグログに以下が表示されます(exec-1は認証が成功した場所、exec-2はexec-1要求によってリダイレクトされた後にiframeが実行する要求です)。
2020-06-24 22:14:02.015 DEBUG 7474 --- [nio-8031-exec-1] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@671fa7ec
2020-06-24 22:14:02.015 DEBUG 7474 --- [nio-8031-exec-1] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2020-06-24 22:14:02.063 DEBUG 7474 --- [nio-8031-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2020-06-24 22:14:02.113 DEBUG 7474 --- [nio-8031-exec-2] o.s.security.web.FilterChainProxy : /launch/development at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-06-24 22:14:02.113 DEBUG 7474 --- [nio-8031-exec-2] o.s.security.web.FilterChainProxy : /launch/development at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-06-24 22:14:02.114 DEBUG 7474 --- [nio-8031-exec-2] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2020-06-24 22:14:02.114 DEBUG 7474 --- [nio-8031-exec-2] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
通常のブラウザウィンドウで同じ実行中のアプリケーションを使用して同じリクエストを実行すると、Spring Securityデバッグログに次のように表示されます。
2020-06-24 22:18:10.518 DEBUG 7474 --- [nio-8031-exec-5] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@671fa7ec
2020-06-24 22:18:10.518 DEBUG 7474 --- [nio-8031-exec-5] w.c.HttpSessionSecurityContextRepository : SecurityContext 'org.springframework.security.core.context.SecurityContextImpl@e1239cdc: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@e1239cdc: Principal: testuserid; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_INSTRUCTOR' stored to HttpSession: 'org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper@66670854
2020-06-24 22:18:10.536 DEBUG 7474 --- [nio-8031-exec-5] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2020-06-24 22:18:10.536 DEBUG 7474 --- [nio-8031-exec-5] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2020-06-24 22:18:10.590 DEBUG 7474 --- [nio-8031-exec-6] o.s.security.web.FilterChainProxy : /home at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-06-24 22:18:10.591 DEBUG 7474 --- [nio-8031-exec-6] o.s.security.web.FilterChainProxy : /home at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-06-24 22:18:10.592 DEBUG 7474 --- [nio-8031-exec-6] w.c.HttpSessionSecurityContextRepository : Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@82a4fa0f: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@82a4fa0f: Principal: testuserid; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_INSTRUCTOR'
私にはこれはかなり奇妙に思えます。これが純粋にブラウザの問題である場合、私がを使用するかどうかは問題ではありませんspring-session-jdbc
。spring-session-jdbc
認証の保存方法に問題がある場合、それが発生するかどうかは問題ではありiframe
ません。私がここで見逃しているものはありますか?バグに遭遇しましたか?
空白のタブでPOSTを実行させるためにiframe内でJavaScriptを使用するという回避策を試すことができますが、それはかなり醜く感じます。
一般的に、iframeでアプリケーションを使用しないことをお勧めします。
これはセキュリティ上のリスクをもたらします。この回答で詳細を確認できます。
次に、表示されている動作を説明します。
Spring SecurityはSession
Cookieを使用してユーザーのセッションを保存します。
Cookieはドメインに関連付けられているため、たとえば、ドメインに関連付けられたCookieがある場合、stackoverflow.com
そのCookieはへのリクエストに含まれますstackoverlow.com
。
その動作を制御するために、Cookieにはという属性もありますSameSite
。属性には、3つの値を持つことができ、または。値がの場合、上記のように動作します(すべてのリクエストに含まれます)。値がの場合、Cookieはトップレベルのナビゲーションリクエストにのみ含まれます。SameSite
None
Lax
Strict
None
Lax
GET
Spring Session依存関係を含めると、Session
cookie SameSite
属性はLax
デフォルトでに設定されます。
iframeでのアプリケーションのレンダリングはトップレベルのナビゲーションでSession
はないため、Cookieはiframeへのリクエストに含まれず、アプリケーションはユーザーがサインインしていることを知る方法がありません。
Springセッションを使用して、SameSite
属性を明示的に設定できますNone
。
繰り返しますが、これはアプリケーションがCSRFおよびクリックジャッキング攻撃に対して脆弱になる可能性があるため、これには注意します。
セキュリティへの影響を考慮した後で、SameSite
属性をに設定する必要があると判断した場合None
は、依存関係にSpring Sessionを含めてカスタムCookieSerializer
を作成することで設定できます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加