最新の安定バージョンについては、Spring Security 6.4.1 を使用してください! |
匿名認証
概要
一般に、許可するものを明示的に指定し、他のすべてを禁止する「デフォルトで拒否」のスタンスを採用することは、適切なセキュリティ慣行と見なされます。認証されていないユーザーがアクセスできるものを定義することは、特に Web アプリケーションの場合と同様の状況です。多くのサイトでは、ユーザーがいくつかの URL 以外(たとえば、ホームページやログインページ)で認証される必要があります。その場合、保護されたすべてのリソースではなく、これらの特定の URL のアクセス構成属性を定義するのが最も簡単です。言い換えると、ROLE_SOMETHING
がデフォルトで必要であり、アプリケーションのログイン、ログアウト、ホームページなど、このルールの特定の例外のみを許可すると言うのがよい場合があります。これらのページをフィルターチェーンから完全に省略して、アクセス制御チェックをバイパスすることもできますが、これは他の理由で、特に認証されたユーザーに対してページの動作が異なる場合は望ましくない場合があります。
これが匿名認証の意味です。「匿名で認証された」ユーザーと認証されていないユーザーの間に実際の概念上の違いはないことに注意してください。Spring Security の匿名認証は、アクセス制御属性を構成するためのより便利な方法を提供します。SecurityContextHolder
に匿名認証オブジェクトが実際に存在する場合でも、getCallerPrincipal
などのサーブレット API 呼び出しへの呼び出しは引き続き null を返します。
監査インターセプターが SecurityContextHolder
にクエリを実行して、特定の操作を担当したプリンシパルを特定する場合など、匿名認証が役立つ状況は他にもあります。SecurityContextHolder
に常に Authentication
オブジェクトが含まれ、null
が含まれないことがわかっている場合、クラスをより堅牢に作成できます。
構成
HTTP 構成 (inSpring Security 3.0 で導入) を使用すると、匿名認証のサポートが自動的に提供されます。<anonymous>
要素を使用して、これをカスタマイズ (または無効化) できます。従来の Bean 構成を使用していない限り、ここで説明する Bean を構成する必要はありません。
3 つのクラスが連携して、匿名認証機能を提供します。AnonymousAuthenticationToken
は Authentication
の実装であり、匿名プリンシパルに適用される GrantedAuthority
インスタンスを格納します。対応する AnonymousAuthenticationProvider
があり、これは ProviderManager
にチェーンされているため、AnonymousAuthenticationToken
インスタンスが受け入れられます。最後に、AnonymousAuthenticationFilter
は通常の認証メカニズムの後にチェーンされ、既存の Authentication
が保持されていない場合は、AnonymousAuthenticationToken
を SecurityContextHolder
に自動的に追加します。フィルターおよび認証プロバイダーは、次のように定義されています。
<bean id="anonymousAuthFilter"
class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<property name="key" value="foobar"/>
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>
<bean id="anonymousAuthenticationProvider"
class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
<property name="key" value="foobar"/>
</bean>
key
はフィルターと認証プロバイダーの間で共有されるため、前者によって作成されたトークンは後者によって受け入れられます
|
userAttribute
は usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]
の形式で表されます。InMemoryDaoImpl
の userMap
プロパティの等号の後に同じ構文が使用されます。
前に説明したように、匿名認証の利点は、次の例に示すように、すべての URI パターンにセキュリティを適用できることです。
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
<property name="securityMetadata">
<security:filter-security-metadata-source>
<security:intercept-url pattern='/index.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
<security:intercept-url pattern='/hello.htm' access='ROLE_ANONYMOUS,ROLE_USER'/>
<security:intercept-url pattern='/logoff.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
<security:intercept-url pattern='/login.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
<security:intercept-url pattern='/**' access='ROLE_USER'/>
</security:filter-security-metadata-source>" +
</property>
</bean>
AuthenticationTrustResolver
匿名認証の議論の締めくくりは、対応する AuthenticationTrustResolverImpl
実装を備えた AuthenticationTrustResolver
インターフェースです。このインターフェースは isAnonymous(Authentication)
メソッドを提供します。これにより、関心のあるクラスはこの特別な型の認証ステータスを考慮に入れることができます。ExceptionTranslationFilter
は、AccessDeniedException
インスタンスの処理にこのインターフェースを使用します。AccessDeniedException
がスローされ、認証が匿名型の場合、403(禁止)レスポンスをスローする代わりに、フィルターは AuthenticationEntryPoint
を開始して、プリンシパルが適切に認証できるようにします。これは必要な区別です。そうしないと、プリンシパルは常に「認証済み」と見なされ、フォーム、基本、ダイジェスト、その他の通常の認証メカニズムを介してログインする機会が与えられることはありません。
以前のインターセプター構成の ROLE_ANONYMOUS
属性が IS_AUTHENTICATED_ANONYMOUSLY
に置き換えられていることがよくあります。これは、アクセス制御を定義する場合と実質的に同じです。これは、認証の章で説明する AuthenticatedVoter
の使用例です。AuthenticationTrustResolver
を使用して、この特定の構成属性を処理し、匿名ユーザーにアクセスを認可します。AuthenticatedVoter
アプローチは、匿名ユーザー、remember-me ユーザー、完全に認証されたユーザーを区別できるため、より強力です。ただし、この機能が必要ない場合は、Spring Security の標準 RoleVoter
によって処理される ROLE_ANONYMOUS
を使用できます。
Spring MVC を使用した匿名認証の取得
独自の引数リゾルバーを使用する Spring MVC は、型 Principal
のパラメーターを解決します。
これは、次のような構成を意味します。
Java
Kotlin
@GetMapping("/")
public String method(Authentication authentication) {
if (authentication instanceof AnonymousAuthenticationToken) {
return "anonymous";
} else {
return "not anonymous";
}
}
@GetMapping("/")
fun method(authentication: Authentication?): String {
return if (authentication is AnonymousAuthenticationToken) {
"anonymous"
} else {
"not anonymous"
}
}
匿名のリクエストであっても、常に「匿名ではない」を返します。その理由は、Spring MVC が HttpServletRequest#getPrincipal
を使用してパラメーターを解決するためです。HttpServletRequest#getPrincipal
は、リクエストが匿名の場合は null
です。
匿名リクエストで Authentication
を取得する場合は、代わりに @CurrentSecurityContext
を使用してください。
Java
Kotlin
@GetMapping("/")
public String method(@CurrentSecurityContext SecurityContext context) {
return context.getAuthentication().getName();
}
@GetMapping("/")
fun method(@CurrentSecurityContext context : SecurityContext) : String =
context!!.authentication!!.name