intercept-url
Springセキュリティで要素にパターンを作成する好ましい方法は何ですか? 私は Web サービス (RESTful) を作成しています。現在、すべてのユーザーがログインし、役割を持っている必要がありますROLE_USER
。@PreAuthorize
次に、サービス層の注釈によってさらに制約が適用されます。intercept-url
ただし、構成が異なる複数の要素も追加するのは一般的ですか?
6 に答える
「好ましい方法」は[必然的に]主観的であると考えるべきです。に<intercept-url>
要素がありましたが、コントローラーの注釈をsecurity.xml
優先してそれらを放棄しました。可能な限り XML 名前空間ではなく Java に保存することを好むので、これは純粋に個人的な好み (私の場合) です。@RequestMapping
@PreAuthorize
どちらか一方、または両方を使用でき、注釈で 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 : 個人的な好みは好みですが、許可の処理に動的な柔軟性が必要な場合は、注釈を使用する必要があります。動的な柔軟性を必要としない場合は、オプションがあります (健全な議論は、名前空間オプションが SoC に関して優れていることを示唆しています)。私は、柔軟性のために Java に処理させることを好みます。XML を設定したら、あとはそのままにして Java に集中したいからです。また、SoC の見解に対するやや説得力のある反論もあります。それは、適切に慣例化された Java アプリケーションは、名前による制御が明らかな見つけやすいパッケージにコントローラーを備えているというものです。
まだ tl;dr : Meh. 1つのうち6つ、もう1つ半ダース。ポテトと言います。
Spring Security を使用するほとんどの Web アプリケーションには、intercept-url
非常に基本的なセキュリティ要件しかないため、いくつかの しかありません。ログイン画面とログインエラー画面、および通常は公開サイトの一部に非認証でアクセスする必要があるため、いくつかの 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 番目の例を使用します。
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>
はい、複数のインターセプト 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 つのプロジェクト間でコントローラー クラスを再利用していて、一方のプロジェクトでコントローラー内のすべてのメソッドに ROLE_USER を許可し、共通コードを使用するもう一方のプロジェクトで ROLE_ADMIN が必要な場合、これを実現する最も簡単な方法は次を使用することです。インターセプト URL。
したがって、@PreAuthorize はハードコードされ、プロジェクト間で共有されることに注意してください。クラスを拡張し、プロジェクトごとに異なる @PreAuthorize を追加できますが、複雑さが増します。
誤ってアノテーションを削除するリスクが少ないため、intercept-url を使用して /user/** のように領域全体を保護するのが好きです。
きめ細かなアクセスを追加する必要がある場合は、既にインターセプト URL によって保護されているコントローラーのメソッドに注釈を追加しますが、これはほとんど発生しません。