Springセキュリティのintercept-url
要素にパターンを作成する好ましい方法は何ですか? Webサービス(RESTful)を作成していますが、現在、すべてのユーザーがログインし、ROLE_USER
ロールを持っている必要があります。その後、サービスレイヤーの@PreAuthorize
アノテーションによってさらに制約が適用されます。ただし、構成が異なる複数のintercept-url
要素を追加することも一般的ですか?
「好ましい方法」は(必然的に)主観的であると考えるべきです。 _<intercept-url>
_に_security.xml
_要素がありましたが、コントローラー上で_@RequestMapping
_を使用した_@PreAuthorize
_アノテーションを優先してそれらを放棄しました。私の場合は、できる限りXML名前空間ではなくJavaに保存することを好むため、純粋に個人的な好みです。
どちらか一方、または両方を使用できます。また、アノテーションにXMLを拡張させることができます。たとえば、次のようなものを使用できます。
security.xml:
_<intercept-url pattern="/something" access="hasRole('ROLE_USER')"/>
_
YourController.Java:
_@RequestMapping(value="/something/else")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String getSomethingElseContents(){ return "somethingelse"; }
_
私が言ったように、それは単に好みの問題のようです。 XML名前空間を使用する利点は、基本アクセスルールがすべて1か所にまとめられており、読みやすく、従いやすいことです。 _@PreAuthorize
_(または他のアノテーションバリアント)によって課される規則は、独自のSpEL式を呼び出すことができ、渡されたパラメーターまたはクラスがアクセス可能なフィールドへのアクセスに基づいて許可決定を行うため、特にセクシーです(つまり@PreAuthorize("@my.project.package.hasMagicPower(#power.INVISIBILITY)")
)、またはこれらの組み合わせ。名前空間オプションでは使用できないロジックと動的な許可を適用できます。
もちろん、「and」、「or」、「!」を使用して基本的なロジックを適用できます。名前空間のSpEL式の接続詞(およびXMLの_@
_指定子を介して外部クラス[boolean]メソッドにアクセスできる場合があります)が、XMLで指定されるものはすべて静的である必要があります。
tl; dr:個人の好みが好みですが、権限の処理に動的な柔軟性が必要な場合、または必要な場合は、have注釈を使用します。動的な柔軟性を望んでおらず、必要でもない場合は、オプションがあります(そして、SoCに関して名前空間オプションが優れていることを示す適切な議論があります)。柔軟性のためにJavaを処理することを好みます。XMLを設定したら、それを地獄のままにしてJavaに焦点を当てたいと思います。また、やや説得力のある反論もあります。 SoCビューへ。これは、適切に従来化されたJavaアプリケーションは、名前で明らかな制御を備えた、見つけやすいパッケージにコントローラーを持っているということです。
まだtl; dr:Meh。 1つのうち6つ、他の6つ。私はpo-tay-toと言います。
Spring Securityを使用するほとんどのWebアプリケーションには、intercept-url
sは、非常に基本的なセキュリティ要件しかないためです。ログイン画面とログインエラー画面への認証されていないアクセスが必要であり、通常は公開サイトの一部であるため、いくつかのURLパターンになります。その後、多くの場合管理セクションがあり、それ以外はすべてROLE_USER
。
さらに多くの役割が必要な場合は、それらを最上位のURLパスコンポーネントに関連付けるのが一般的です。必須ではありませんが、リソースが適切に保護されていることを確認しやすくなります。
<http realm="Contacts Realm" use-expressions="false">
<intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/admin/*" access="ROLE_ADMIN"/>
<intercept-url pattern="/secret/*" access="ROLE_SECRET"/>
<intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN,ROLE_SECRET"/>
<http-basic/>
</http>
ユースケースに基づいて、人々が複数の役割を持つことを許可するかどうかを決定する必要があります。アプリで管理するのは少し難しいので、セキュリティがシンプルなほとんどのユーザーは、ユーザーが1つのロールを持ち、複数のロールが保護されたコンテンツにアクセスできるようにセットアップします。もちろん、もう1つの方法は、URLパターンごとに1つの役割を割り当て、人々に複数の役割を与えることです。
とにかく、あなたの質問(または少なくともあなたが尋ねていると思う質問)に対する答えは、通常行うべきことは、同じセキュリティ制限を持つすべてのリソースを保護する役割ごとに1つのトップレベルパスコンポーネントです。もちろん、そのパスプレフィックスの下に機能をグループ化するので、この構造を嫌う人もいれば、コードで注釈を使用することを好む人もいます。私は1つの場所でそれを見ることができ、URLを見ることでセキュリティの期待が何であるかを簡単に知ることができる私のセキュリティが好きです。
SpringSecurityの構成は、アプリケーションに対して選択した認証によって異なります。たとえば、フォーム認証の場合、許可なしでログインURLとログアウト成功URLを構成します。
<http realm="Contacts Realm">
<intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/**" access="ROLE_USER"/>
<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1"/>
<logout logout-success-url="/index.jsp"/>
</http>
基本認証の場合、ログインURLとログアウトURLがなく、構成はより簡単です。
<http realm="Contacts Realm">
<intercept-url pattern="/**" access="ROLE_USER"/>
<http-basic/>
</http>
基本認証を選択する場合は、2番目の例を使用します。
はい、複数のintercept-urlパターンを定義し、その上に特定のリソースをさらに制限するために注釈を追加することは非常に一般的です。
また、各制限にディレクトリを使用して、注釈が不要になるようにすることもできます。例/ user/**にはROLE_USERが必要、/ admin/**にはROLE_ADMINなどが必要.
どちらの方法を使用する場合でも、間違えた場合のセキュリティへの影響に留意してください。
インターセプトURLを使用する場合、次のように行を正しい順序で配置する必要があります。
<intercept-url pattern="/**" access="permitAll"/>
<intercept-url pattern="/user/**" access="hasRole('ROLE_USER')"/>
最初の行ですべてのアクセスをグレーティングしているため、機能しません。そのため、行を逆にする必要があります。初心者がプロジェクトに取り組んでいて、行を逆にすると、大きな問題になる可能性があります。
注釈を使用する場合、誤って注釈行を削除して、アプリケーションにセキュリティホールを残すことができます。
@PreAuthorize("hasRole('ROLE_USER')")
2つのプロジェクト間でコントローラークラスを再利用しており、1つのプロジェクトでROLE_USERをコントローラー内のすべてのメソッドに許可し、共通コードを使用する他のプロジェクトにROLE_ADMINが必要な場合、それを実現する最も簡単な方法はインターセプトURL。
したがって、@ PreAuthorizeはハードコーディングされ、プロジェクト間で共有されることに注意してください。クラスを拡張し、プロジェクトごとに異なる@PreAuthorizeを追加できますが、さらに複雑になります。
誤って注釈を削除するリスクが少ないため、intercept-urlを使用して/ user/**などの領域全体を保護するのが好きです。
きめ細かなアクセスを追加する必要がある場合は、intercept-urlで既に保護されているコントローラーのメソッドに注釈を追加しますが、これはめったに起こりません。
URLのインターセプトは、この方法で実行できます。レストサービスのURLが/rest/
で始まるとします。
<http auto-config="true" use-expressions="true" access-denied-page="/accessDeniedPageURL">
<intercept-url pattern="/rest/**" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/view/products" access="isFullyAuthenticated()"/>
<form-login login-page="/landing" default-target-url="/view/products" authentication-failure-handler-ref="authenticationFailureHandler"/>
<logout invalidate-session="true" logout-success-url="/landing" delete-cookies="JSESSIONID"/>
<session-management invalid-session-url="/landing" session-authentication-error-url="/landing?msg=alreadyLogin">
<concurrency-control max-sessions="1" expired-url="/landing?msg=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
</session-management>
</http>
一般に、Spring Securityはロールベースのアクセスに適しています。そしてそれはそれについてです。独自のProcessingFilterを作成して、追加の処理を実行できます。しかし、私はこれが少しの利益のために多くの仕事であることがわかります。
別の方法は、リクエストインターセプターを使用することです。 Spring MVCを使用したRESTfulサービスのいくつかのプロジェクトでは、リクエストインターセプターを利用して、基本的なロールアクセスを超えた認証を完了します。これは機能し、私の意見では、一連のイベントを追跡するのがはるかに簡単になりますが、1分間に数千のトランザクションを処理している場合、リクエストが行き詰まる可能性があります。