2013-03-20 18 views
5

2つのURLセットがあります.1つはREST API、もう1つはかなり普通のWebサイトです。 REST APIに別のセキュリティルールを適用して、時にはREST APIを呼び出すユーザー/スクリプトが401コード(基本認証は問題ありません)に応答するようにします。 - または403だけです。Spring Security - REST APIと他のURLの個別の設定

  • ログインしているユーザー(REST APIを呼び出すサイトページのjavascriptが同じセッションを共有するため)のためのREST APIへのアクセス。
  • WWW-Authenticateヘッダーの基本認証資格情報でREST APIを呼び出すスクリプト。

現時点では、私が欲しいものを「理解する」ためにどのような構成が妥当なものになるのか理解しようとしています。 私は、次の設定を思い付いた:

<beans:beans xmlns="http://www.springframework.org/schema/security" 
      xmlns:beans="http://www.springframework.org/schema/beans" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation=" 
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 
    <http pattern="/" security="none" /> 
    <http pattern="/static/**" security="none" /> 

    <!-- REST API --> 
    <http pattern="/rest/*" use-expressions="true"> 
     <http-basic /> 
     <intercept-url pattern="/*" access="isAuthenticated()" /> 
    </http> 

    <!-- Site --> 
    <http access-denied-page="/WEB-INF/views/errors/403.jsp" use-expressions="true"> 
     <intercept-url pattern="/index.html" access="hasRole('ROLE_USER') or hasRole('ROLE_ANONYMOUS')" /> 
     <intercept-url pattern="/login.html" access="hasRole('ROLE_USER') or hasRole('ROLE_ANONYMOUS')" /> 
     <intercept-url pattern="/admin/*" access="hasRole('ROLE_ADMIN')" /> 
     <intercept-url pattern="/**" access="hasRole('ROLE_USER')" /> 
     <form-login login-page="/login.html" 
        default-target-url="/index.html" 
        authentication-failure-url="/login.html?error=1" /> 

     <logout logout-url="/logout.do" logout-success-url="/index.html" /> 

     <anonymous username="guest" granted-authority="ROLE_ANONYMOUS" /> 
     <remember-me /> 
    </http> 

    <authentication-manager> 
     <authentication-provider> 
      <user-service> 
       <user name="admin" password="2" authorities="ROLE_ADMIN,ROLE_USER" /> 
       <user name="alex" password="1" authorities="ROLE_USER" /> 
      </user-service> 
     </authentication-provider> 
    </authentication-manager> 
</beans:beans> 

残念ながら、基本認証だけではなく、この設定では動作しませんが、匿名ユーザーによって行われた要求のための403個の応答がありません - 私は思い見つかりリダイレクト302を使用してアプリケーションの答えはREST APIのURLを許可しないようにします。

私は、REST APIのカスタムエントリポイントを追加しようとしました:

<beans:bean id="ep403" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/> 


<!-- REST API --> 
<http pattern="/rest/*" entry-point-ref="ep403" use-expressions="true"> 
    <intercept-url pattern="/*" access="hasRole('ROLE_USER')" /> 
    <http-basic /> 
</http> 

が、これはどちらか動作しません。

は、私が取得したいん何を要約すると:

  • は(許可機能は、アカウントにクッキーでユーザーセッションを取る必要があります)許可されたユーザは、REST APIへのアクセスを許可します。
  • 正しい認証トークンが指定されていて、クッキーにセッションが指定されていない場合、スクリプトはREST APIにアクセスできます。

UPDATE

春のセキュリティの内部に掘り後、私は特定の要求かどうかを拒否するかどうかを決定するコードを発見しました。これはいわゆる「アクセス決定有権者」であり、基本的にはすべてが特定の要求に適用され、チェーン内の1人のアクセス決定有権者が特定のリソースへのアクセスを拒否した場合、要求は最終的に拒否されます。

したがって、セッションから関連ロールを抽出しようとします(リクエスト内に存在する場合)。このロールで承認ステップに進みます。セッションが存在しない場合、WWW-Authenticateヘッダーの資格情報に対してユーザーを認証しようとし、指定されたユーザーに関連付けられたロールを使用して承認手順に進みます。

答えて

3

青い@の解決策としてReposting:提案は、これが誰かを助けることを願っています。

私は簡単な回避策を見つけました。私は、URLの二つの異なるセットに1つの、残りのコントローラをマッピングし、春のセキュリティの設定で個別の認証ハンドラに各セットを割り当て:

<!-- Defines custom security policy for Stateful REST API --> 
<beans:bean id="nonRedirectingAccessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl"/> 
<beans:bean id="forbiddenEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/> 

<!-- Stateful REST API --> 
<http pattern="/rest/stateful/**" use-expressions="true" entry-point-ref="forbiddenEntryPoint"> 
    <access-denied-handler ref="nonRedirectingAccessDeniedHandler"/> 
    <intercept-url pattern="/rest/stateful/**" access="isAuthenticated()" /> 
</http> 

<!-- Stateless REST API --> 
<http pattern="/rest/stateless/**" use-expressions="true" create-session="stateless"> 
    <http-basic/> 
    <intercept-url pattern="/rest/stateless/**" access="isAuthenticated()" /> 
</http> 

それは将来的にあなたがしたいことがあるため、その問題への良いアプローチのように見えますユーザーまたはスクリプトのユースケースに固有の固有のURLを使用して、ステートフルな-userまたはステートレスの-script REST APIを拡張します。

私のケースでは、UXの変更で特定のUIシナリオを実装するために設計されたいくつかの新しいメソッドを提供するREST APIが必要な場合があり、スクリプトシナリオによっては特定のクライアントスクリプトとサーバーの対話をサポートするために

0

は、REST APIのpattern="/**"pattern="/rest/**"pattern="/*"pattern="/rest/*"を変更しよう:

<http pattern="/rest/**" use-expressions="true"> 
    <intercept-url pattern="/**" access="isAuthenticated()" /> 
    <http-basic /> 
</http> 
+0

ありがとうございます、create-sessionはトリックですが、基本認証が動作することを拒否されたセッションによる認証が行われます(つまり、ページ上のjavascriptはREST APIにアクセスできなくなります)。 – Alex

+0

はい、それは本当です。パターンを変更すると便利でしたか? –

+0

パターンはあまり影響を受けていませんが、非常にシンプルなREST APIのURLスキーム(/ rest/book?name = Xのように、私は正当な負担に悩まされています。 。もちろん、/ rest/one/twoのようなネストが深いURLに対しては、私のパターンはうまくいかないでしょう、これを指摘してくれてありがとう。 create-session = "stateless"は両方のパターンの基本的な認証作業を行いますが、両方のパターンのために既存の許可されたセッションも春に無視します。 – Alex

2

あなたは/rest/パターンを有するURLを確認するためにインターセプタを使用することができます。このため

<mvc:interceptors> 
     <mvc:interceptor> 
      <mvc:mapping path="/rest/**"/> 
      <bean class="com.your.class.name.Interceptor></bean> 
     </mvc:interceptor> 
</mvc:interceptors> 

、XMLのヘッダ部分に以下の行を追加します。あなたに必要なものは何でもInterceptorクラスチェックで今すぐすなわち

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" 

と、このクラスは春HandlerInterceptorを実装する必要があります。

public class Interceptor implements HandlerInterceptor{ 

    @Override 
    public boolean preHandle(HttpServletRequest request, 
          HttpServletResponse response, 
          Object handler) throws Exception { 
     //do what you need to check when the request arrives 
     //do authentications here 
     //return true if success 
     //else false 
    } 

    @Override 
    public void postHandle(HttpServletRequest request, 
          HttpServletResponse response, 
          Object handler, 
          ModelAndView modelAndView) throws Exception { 

    } 

    @Override 
    public void afterCompletion(HttpServletRequest request, 
           HttpServletResponse response, 
           Object handler, 
           Exception ex) throws Exception {  
    } 

} 

詳細については、thisを参照してください。 また、見ることができますthis

+0

私はあなたがきちんと正しいと確信していません。私があなたのアプローチを正しく理解していれば、提案されたインターセプタに必要なすべての認証ロジックを実装する必要があり、security-context.xmlとそのようなカスタムインターセプタにセキュリティ設定が広がります。ちょっと恐ろしい。まあ、これが唯一の解決策であれば、REST URLに関する認証と承認のための私のアプローチを再考したいと思います。 – Alex

+0

はい、あなたはそれを得ました。どういうことですか? – Anubhab

+0

現時点では、私はロードバランサ側でやっていると思います。これは非常に困難で壊れやすいアプローチですが、うまくいきます。同時に私は積極的にこの問題の適切な春のセキュリティのみのソリューションを探しています。私は、基本認証を削除し、REST APIを使用するスクリプト用の別のログインURLを含める方法で、私のアプローチを再考することができます。 – Alex

関連する問題