匿名認証

概要

一般に、許可するものを明示的に指定し、他のすべてを禁止する「デフォルトで拒否」のスタンスを採用することは、適切なセキュリティ慣行と見なされます。認証されていないユーザーがアクセスできるものを定義することは、特に Web アプリケーションの場合と同様の状況です。多くのサイトでは、ユーザーがいくつかの URL 以外(たとえば、ホームページやログインページ)で認証される必要があります。その場合、保護されたすべてのリソースではなく、これらの特定の URL のアクセス構成属性を定義するのが最も簡単です。言い換えると、ROLE_SOMETHING がデフォルトで必要であり、アプリケーションのログイン、ログアウト、ホームページなど、このルールの特定の例外のみを許可すると言うのがよい場合があります。これらのページをフィルターチェーンから完全に省略して、アクセス制御チェックをバイパスすることもできますが、これは他の理由で、特に認証されたユーザーに対してページの動作が異なる場合は望ましくない場合があります。

これが匿名認証の意味です。「匿名で認証された」ユーザーと認証されていないユーザーの間に実際の概念上の違いはないことに注意してください。Spring Security の匿名認証は、アクセス制御属性を構成するためのより便利な方法を提供します。SecurityContextHolder に匿名認証オブジェクトが実際に存在する場合でも、getCallerPrincipal などのサーブレット API 呼び出しへの呼び出しは引き続き null を返します。

監査インターセプターが SecurityContextHolder にクエリを実行して、特定の操作を担当したプリンシパルを特定する場合など、匿名認証が役立つ状況は他にもあります。SecurityContextHolder に常に Authentication オブジェクトが含まれ、null が含まれないことがわかっている場合、クラスをより堅牢に作成できます。

構成

HTTP 構成 (Spring Security 3.0 で導入) を使用すると、匿名認証サポートが自動的に提供されます。<anonymous> 要素を使用してカスタマイズ (または無効化) できます。従来の Bean 構成を使用しない限り、ここで説明する Bean を構成する必要はありません。

3 つのクラスが連携して匿名認証機能を提供します。AnonymousAuthenticationToken は Authentication の実装であり、匿名プリンシパルに適用される GrantedAuthority インスタンスを格納します。対応する AnonymousAuthenticationProvider があり、AnonymousAuthenticationToken インスタンスが受け入れられるように ProviderManager にチェーンされています。最後に、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 はフィルターと認証プロバイダーの間で共有されるため、前者によって作成されたトークンは後者によって受け入れられます

key プロパティの使用は、ここで実際のセキュリティを提供するものと見なされるべきではありません。それは単なる簿記の練習です。認証クライアントが Authentication オブジェクトを作成できるシナリオ(RMI 呼び出しなど)で AnonymousAuthenticationProvider を含む ProviderManager を共有する場合、悪意のあるクライアントは、自分で作成した AnonymousAuthenticationToken を(選択したものを使用して)送信する可能性があります。ユーザー名と権限リスト)。key が推測可能であるか、検出できる場合、トークンは匿名プロバイダーによって受け入れられます。これは通常の使用では問題ありません。ただし、RMI を使用する場合は、HTTP 認証メカニズムに使用するプロバイダーを共有するのではなく、匿名プロバイダーを省略したカスタマイズされた ProviderManager を使用する必要があります。

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 を使用してください。

匿名のリクエストには CurrentSecurityContext を使用する
  • Java

  • Kotlin

@GetMapping("/")
public String method(@CurrentSecurityContext SecurityContext context) {
	return context.getAuthentication().getName();
}
@GetMapping("/")
fun method(@CurrentSecurityContext context : SecurityContext) : String =
		context!!.authentication!!.name