2011-07-31 29 views
20

私たちは以下のようなURLへのアクセスを定義するためにインターセプト-URLタグを使用します。Springセキュリティで<intercept-url>アクセス属性値を動的に決定する方法は?春のセキュリティで

<intercept-url pattern="/**" access="ROLE_ADMIN" /> 
<intercept-url pattern="/student" access="ROLE_STUDENT" /> 

。これは、ハードapplicationContext-security.xmlでコード化されます。代わりにデータベーステーブルからアクセス値を読みたいと思います。私自身がUserDetailsServiceを定義しており、ログインしたユーザーのロールをデータベースから読み取りました。実行時にこれらのロールをURLパターンに割り当てるにはどうすればよいですか?

+0

それが役に立つかもしれません:します。https:

<intercept-url pattern="/**/**" access="#{@customAuthenticationProvider.returnStringMethod}" /> <intercept-url pattern="/**" access="#{@customAuthenticationProvider.returnStringMethod}" /> 

customAuthenticationProviderは、作成方法CustomAuthenticationProviderクラス内のBean

<beans:bean id="customAuthenticationProvider" class="package.security.CustomAuthenticationProvider" /> 

ある//github.com/srinivas1918/spring-security-dynamic -authorization-and-authentication –

答えて

18

春セキュリティでFilterInvocationSecurityMetadataSourceParserクラスSecurityMetadataSourceを拡張FilterInvocationSecurityMetadataSourceを実装DefaultFilterInvocationSecurityMetadataSourceを延びる、インターセプト-URLタグを解析し、ExpressionBasedFilterInvocationSecurityMetadataSourceのインスタンスを作成する(Ctrlキー/ CMDが+ソースコードをSTSに+ Tシフトしてみてください)。

私が行ったのは、FilterInvocationSecurityMetadataSourceを実装するカスタムクラスを作成することです。OptionsFromDataBaseFilterInvocationSecurityMetadataSource私はDefaultFilterInvocationSecurityMetadataSourceをベースとしてurlMatcherを使用して、support()メソッドなどを実装しました。

その後の作業を行う必要があり、これらのメソッドを実装するには:取得するためにデータベースにアクセスすることができ

  • コレクションのgetAttributes(Objectオブジェクト)、「オブジェクト」の検索が確保されている(アクセスには通常URLを)許可ConfigAttributeの(通常はROLEの)

  • ブールサポート(クラスclazz)

  • コレクションgetAllConfigAttributes()

起動時に呼び出され、現在はよく設定されていない(つまり、使用しているデータソースまたは永続コンテキストがautowiredであるため)、後で注意してください。 Web環境のソリューションは、web.xml内のcontextConfigLocationを設定して、applicationContext.xmlをapplicationContext-security.xmlの前にロードすることです。

最後に、このBeanをロードするようにapplicationContext-security.xmlをカスタマイズします。

はそれを行うために、私は代わりにセキュリティ名前空間のこのファイルには、通常の豆を使用:

<beans:bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy"> 
    <filter-chain-map path-type="ant"> 
     <filter-chain pattern="/images/*" filters="none" /> 
     <filter-chain pattern="/resources/**" filters="none" /> 
     <filter-chain pattern="/**" filters=" 
     securityContextPersistenceFilter, 
     logoutFilter, 
     basicAuthenticationFilter, 
     exceptionTranslationFilter, 
     filterSecurityInterceptor" 
    /> 
    </filter-chain-map> 
</beans:bean> 

あなたは、関連するすべての豆を定義する必要があります。例えば:

<beans:bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"> 
    <beans:property name="authenticationManager" ref="authenticationManager"></beans:property> 
    <beans:property name="accessDecisionManager" ref="affirmativeBased"></beans:property> 
    <beans:property name="securityMetadataSource" ref="optionsFromDataBaseFilterInvocationSecurityMetadataSource"></beans:property> 
    <beans:property name="validateConfigAttributes" value="true"/></beans:bean> 

私はそれがうまく説明答えではないですけど、それは思ったほど難しいことではありません。

スプリングソースをベースとして使用するだけで、必要なものを手に入れることができます。

データベース内のデータを使用してデバッグすると、多くの作業に役立ちます。

+0

私はstruts2と同じことを達成しようとしています。 Spring Security 3.1を通過しましたが、struts2との統合に関する十分なアイデアは得られませんでした2。 struts2と統合するための基本的な考え方を教えていただけますか? – SunJCarkeY

+0

この例は古いバージョンの春です。私は春のセキュリティ3.2の下でそれを行うことができますか? – ajaristi

2

私は同じ問題を抱えていますが、基本的には、他のスプリングセクション構成セクションからのインターセプトURLのリストを分離しておく必要があります。アプリケーション構成に属する最初のもの(コア、プラグイン)構成。

この問題に関しては、春のJIRAにproposalがあります。

私はspringsecurity名前空間を使用することをあきらめたくないので、私はこれに対処するためにいくつかの解決策を考えていました。

intercept-urlのリストを動的に作成するには、securitymetadatasourceオブジェクトをFilterSecurityInterceptorに注入する必要があります。 使用springsecurityスキーマFilterSecurityInterceptorのインスタンスがHttpBuilderクラスによって作成することができた、回避策の種類を使用するなど、以下のように、スキーマ構成ファイルで定義されたプロパティとしてsecuritymetadatasourceを渡す方法はありませんされている。

  • FilterSecurityInterceptorの前に実行されるカスタムフィルタを定義します。このフィルタでは、SpringのコンテキストによってインスタンスのFilterSecurityInterceptor(一意のhttpセクションが定義されていると仮定します)を取得し、そこにsecuritymetadatasourceインスタンスを注入します。
  • 上記と同じですが、HandlerInterceptorにあります。

あなたはどう思いますか?

1

これは、インターセプトURLエントリのリストを他のスプリングセキュリティコンフィグレーションから分割するために適用したソリューションです。

<security:custom-filter ref="parancoeFilterSecurityInterceptor" 
     before="FILTER_SECURITY_INTERCEPTOR" /> 
........ 

<bean id="parancoeFilterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor" > 
    <property name="authenticationManager" ref="authenticationManager"/> 
    <property name="accessDecisionManager" ref="accessDecisionManager"/> 
    <property name="securityMetadataSource" ref="securityMetadataSource"/> 
</bean> 

bean securityMetadataSourceは、同じ構成ファイルまたは別の構成ファイルに置くことができます。もちろん

<security:filter-security-metadata-source 
    id="securityMetadataSource" use-expressions="true"> 
    <security:intercept-url pattern="/admin/**" 
     access="hasRole('ROLE_ADMIN')" /> 
</security:filter-security-metadata-source> 

あなたは、インタフェースFilterInvocationSecurityMetadataSourceを実装することで、独自のsecurityMetadataSource Beanを実装することを決定することができます。このような 何か:

<bean id="securityMetadataSource" class="mypackage.MyImplementationOfFilterInvocationSecurityMetadataSource" /> 

は、この情報がお役に立てば幸いです。

+0

私はまったく同じ解決策に終わった。残念ながら、定義を分割する簡単な方法はありません。 –

4

実際には、スプリングセキュリティ3.2は、カスタムaccessDecisionManagerで名前空間でのhttp要素を使用して、それは(エレガントではない)ことが可能であり、http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/faq.html#faq-dynamic-url-metadata

に応じてこれを行うことをお勧めしませんが...

設定すべきです:

<http pattern="/login.action" security="none"/> 
<http pattern="/media/**" security="none"/> 

<http access-decision-manager-ref="accessDecisionManager" > 
    <intercept-url pattern="/**" access="ROLE_USER"/> 
    <form-login login-page="/login.action" 
       authentication-failure-url="/login?error=1" 
       default-target-url="/console.action"/> 
    <logout invalidate-session="true" delete-cookies="JSESIONID"/> 
    <session-management session-fixation-protection="migrateSession"> 
     <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" expired-url="/login.action"/> 
    </session-management> 

    <!-- NO ESTA FUNCIONANDO, los tokens no se ponen en el request! 
    <csrf /> 
    --> 

</http> 
<authentication-manager> 
    <authentication-provider> 
     <user-service> 
      <user name="test" password="test" authorities="ROLE_USER" /> 
     </user-service> 
    </authentication-provider> 
</authentication-manager> 

<beans:bean id="accessDecisionManager" class="openjsoft.core.services.security.auth.CustomAccessDecisionManager"> 
    <beans:property name="allowIfAllAbstainDecisions" value="false"/> 
    <beans:property name="decisionVoters"> 
    <beans:list> 
     <beans:bean class="org.springframework.security.access.vote.RoleVoter"/> 
    </beans:list> 
    </beans:property> 
</beans:bean> 

CustomAccessDecisionManagerが...

public class CustomAccessDecisionManager extends AbstractAccessDecisionManager { 
... 

public void decide(Authentication authentication, Object filter, 
     Collection<ConfigAttribute> configAttributes) 
     throws AccessDeniedException, InsufficientAuthenticationException { 

    if ((filter == null) || !this.supports(filter.getClass())) { 
     throw new IllegalArgumentException("Object must be a FilterInvocation"); 
    } 

    String url = ((FilterInvocation) filter).getRequestUrl(); 
    String contexto = ((FilterInvocation) filter).getRequest().getContextPath(); 

    Collection<ConfigAttribute> roles = service.getConfigAttributesFromSecuredUris(contexto, url); 



    int deny = 0; 

    for (AccessDecisionVoter voter : getDecisionVoters()) { 
     int result = voter.vote(authentication, filter, roles); 

     if (logger.isDebugEnabled()) { 
      logger.debug("Voter: " + voter + ", returned: " + result); 
     } 

     switch (result) { 
     case AccessDecisionVoter.ACCESS_GRANTED: 
      return; 

     case AccessDecisionVoter.ACCESS_DENIED: 

      deny++; 

      break; 

     default: 
      break; 
     } 
    } 

    if (deny > 0) { 
     throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied", 
       "Access is denied")); 
    } 

    // To get this far, every AccessDecisionVoter abstained 
    checkAllowIfAllAbstainDecisions(); 
} 

... 
} 
する必要があります getConfigAttributesFromSecuredUrisは、特定のURLのフォームDBデロールを取得

0

これは、春のセキュリティ3.2で行うことができる方法である。

@Configuration 
@EnableWebMvcSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Bean 
    public SecurityConfigDao securityConfigDao() { 
     SecurityConfigDaoImpl impl = new SecurityConfigDaoImpl() ; 
     return impl ; 
    } 



    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     /* get a map of patterns and authorities */ 
     Map<String,String> viewPermissions = securityConfigDao().viewPermissions() ; 

     ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry interceptUrlRegistry = http 
     .authorizeRequests().antMatchers("/publicAccess/**") 
     .permitAll(); 

     for (Map.Entry<String, String> entry: viewPermissions.entrySet()) { 
      interceptUrlRegistry.antMatchers(entry.getKey()).hasAuthority(entry.getValue()); 
     } 

     interceptUrlRegistry.anyRequest().authenticated() 
     .and() 
     ... 
     /* rest of the configuration */ 
    } 
} 
1

私の作品シンプルなソリューション。

public synchronized String getReturnStringMethod() 
{ 
    //get data from database (call your method) 

    if(condition){ 
     return "IS_AUTHENTICATED_ANONYMOUSLY"; 
    } 
    return "ROLE_ADMIN,ROLE_USER"; 
} 
関連する問題