4

最近、Spring構成の大部分を、Spring3.1のコードベースの構成を使用するように切り替えました。ただし、切り替えたので、Spring Securityが正しく機能せず、Tomcatの起動時に次のエラーがスローされます。

SEVERE: Exception starting filter springSecurityFilterChain
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named     'springSecurityFilterChain' is defined

私はまだXMLファイルにSpringSecurityを持っており、これはカスタム名前空間であるためSpringでJava構成に変換できないことを知っていますが、Java構成ファイル内で参照しています。また、applicationContext-security.xml構成参照をJava構成から自分のweb.xmlに移動しようとしましたが、運がありませんでした。

@Configuration
@EnableWebMvc
@Import(ServicesConfig.class)
@ImportResource({ "classpath:applicationContext-security.xml",
"classpath:dataSources.xml" })
@ComponentScan(basePackages = "com.foobar")
public class WebConfig {
   // left out Beans for clarity
}

applicationContext-security.xml:

<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
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://www.springframework.org/schema/security/oauth2
      http://www.springframework.org/schema/security/spring-security-oauth2.xsd">

<!-- Security configuration -->

<global-method-security pre-post-annotations="enabled" />

<http use-expressions="true" access-denied-page="/error/accessDenied" 
        entry-point-ref="casEntryPoint">
    <intercept-url pattern="/**" access="isAuthenticated()" />
    <custom-filter position="CAS_FILTER" ref="casFilter" />
</http>

<authentication-manager alias="authenticationManager">
    <authentication-provider ref="casAuthenticationProvider" />
</authentication-manager>

<!-- Bean definitions -->
<b:bean id="casAuthenticationProvider"
    class="org.springframework.security.cas.authentication.CasAuthenticationProvider"
    p:serviceProperties-ref="serviceProperties" p:key="1234"
    p:authenticationUserDetailsService-ref="userDetailsByNameServiceWrapper"
    p:ticketValidator-ref="cas20ServiceTicketValidator" />

<b:bean id="userDetailsByNameServiceWrapper"
    class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"
    c:userDetailsService-ref="userDetailsService" />

<b:bean id="userDetailsService" class="foobar.MyUserDetailsService" />

<b:bean id="cas20ServiceTicketValidator" 
    class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator"
    c:casServerUrlPrefix="https://mycasserver/cas" />

<b:bean id="casFilter"
    class="org.springframework.security.cas.web.CasAuthenticationFilter"
    p:authenticationManager-ref="authenticationManager" />

<b:bean id="casEntryPoint"
    class="org.springframework.security.cas.web.CasAuthenticationEntryPoint"
    p:loginUrl="https://mycasserver/cas/login" 
    p:serviceProperties-ref="serviceProperties" />

<b:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties"
    p:service="https://foobar.com/services/j_spring_cas_security_check"
    p:sendRenew="false" />

</b:beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<description>My App</description>

<!-- Context Params -->
<context-param>
    <param-name>contextClass</param-name>
    <param-value>
         org.springframework.web.context.support.AnnotationConfigWebApplicationContext
    </param-value>
</context-param>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>foobar.WebConfig</param-value>
</context-param>

<!-- Filters --> 
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Listeners -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Servlets -->
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
         </param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

</web-app>
4

4 に答える 4

8

名前空間のショートカットを使用せずsecurity、すべてのSpring構成をXMLからJavaに移行します。これにより、セキュリティの微調整がはるかに簡単になります。3.1に移行した後、すぐにプロジェクトで実行します。ここで、自明ではないほぼプレーンなセキュリティXML構成の例を見つけることができます

編集: 構成(上記のリンク)の移行が完了しました。すべての構成は、フィルターごとに個別のSpring Beanを必要としないことを示すために、意図的に1つのメソッドにまとめられています。もちろん、複雑なinitパーツを別々のメソッドに移動することをお勧めします(@Bean必要に応じてマークを付けます)。X509AnnotationTest.Config上記のリンクで実際の例を見つけることができます。

@Bean
public FilterChainProxy springSecurityFilterChain() throws Exception {
    // AuthenticationEntryPoint
    BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
    entryPoint.setRealmName("AppName Realm");
    // accessDecisionManager
    List<AccessDecisionVoter> voters = Arrays.<AccessDecisionVoter>asList(new RoleVoter(), new WebExpressionVoter());
    AccessDecisionManager accessDecisionManager = new AffirmativeBased(voters);
    // SecurityExpressionHandler
    SecurityExpressionHandler<FilterInvocation> securityExpressionHandler = new DefaultWebSecurityExpressionHandler();
    // AuthenticationUserDetailsService
    UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken> authenticationUserDetailsService = new UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken>(authUserDetailService);
    authenticationUserDetailsService.afterPropertiesSet();
    // PreAuthenticatedAuthenticationProvider
    PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider = new PreAuthenticatedAuthenticationProvider();
    preAuthenticatedAuthenticationProvider.setPreAuthenticatedUserDetailsService(authenticationUserDetailsService);
    preAuthenticatedAuthenticationProvider.afterPropertiesSet();
    // AuthenticationManager
    List<AuthenticationProvider> providers = Arrays.<AuthenticationProvider>asList(preAuthenticatedAuthenticationProvider);
    AuthenticationManager authenticationManager = new ProviderManager(providers);
    // HttpSessionSecurityContextRepository
    HttpSessionSecurityContextRepository httpSessionSecurityContextRepository = new HttpSessionSecurityContextRepository();
    // SessionRegistry
    SessionRegistry sessionRegistry = new SessionRegistryImpl();
    // ConcurrentSessionControlStrategy
    ConcurrentSessionControlStrategy concurrentSessionControlStrategy = new ConcurrentSessionControlStrategy(sessionRegistry);

    // ConcurrentSessionFilter
    ConcurrentSessionFilter concurrentSessionFilter = new ConcurrentSessionFilter(sessionRegistry);
    concurrentSessionFilter.afterPropertiesSet();
    // SecurityContextPersistenceFilter
    SecurityContextPersistenceFilter securityContextPersistenceFilter = new SecurityContextPersistenceFilter(httpSessionSecurityContextRepository);
    // X509AuthenticationFilter
    X509AuthenticationFilter x509AuthenticationFilter = new X509AuthenticationFilter();
    x509AuthenticationFilter.setAuthenticationManager(authenticationManager);
    x509AuthenticationFilter.afterPropertiesSet();
    // RequestCacheAwareFilter
    RequestCacheAwareFilter requestCacheAwareFilter = new RequestCacheAwareFilter();
    // SecurityContextHolderAwareRequestFilter
    SecurityContextHolderAwareRequestFilter securityContextHolderAwareRequestFilter = new SecurityContextHolderAwareRequestFilter();
    // SessionManagementFilter
    SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(httpSessionSecurityContextRepository, concurrentSessionControlStrategy);
    // ExceptionTranslationFilter
    ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter(entryPoint);
    exceptionTranslationFilter.setAccessDeniedHandler(new AccessDeniedHandlerImpl());
    exceptionTranslationFilter.afterPropertiesSet();
    // FilterSecurityInterceptor
    FilterSecurityInterceptor filterSecurityInterceptor = new FilterSecurityInterceptor();
    filterSecurityInterceptor.setAuthenticationManager(authenticationManager);
    filterSecurityInterceptor.setAccessDecisionManager(accessDecisionManager);
    LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> map = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>();
    map.put(new AntPathRequestMatcher("/**"), Arrays.<ConfigAttribute>asList(new SecurityConfig("isAuthenticated()")));
    ExpressionBasedFilterInvocationSecurityMetadataSource ms = new ExpressionBasedFilterInvocationSecurityMetadataSource(map, securityExpressionHandler);
    filterSecurityInterceptor.setSecurityMetadataSource(ms);
    filterSecurityInterceptor.afterPropertiesSet();
    // SecurityFilterChain
    SecurityFilterChain chain = new DefaultSecurityFilterChain(new AntPathRequestMatcher("/**"),
            concurrentSessionFilter,
            securityContextPersistenceFilter,
            x509AuthenticationFilter,
            requestCacheAwareFilter,
            securityContextHolderAwareRequestFilter,
            sessionManagementFilter,
            exceptionTranslationFilter,
            filterSecurityInterceptor);
    return new FilterChainProxy(chain);
}
于 2012-04-04T19:11:50.490 に答える
7

SpringSecurityXML構成をJava構成Webアプリケーションで使用する方法をまだ探している人のために。Spring3.2.0.RELEASEとSpringSecurity3.2.0.M1を使用してこれを機能させました。これがソリューションの重要な部分です

WebAppConfig.java

package com.foo.webapp;

@Configuration
@ComponentScan(basePackages = { "com.foo" })
@ImportResource(value = { "/WEB-INF/spring-security.xml" })
public class WebAppConfig {
    // other beans go here
}

spring-security.xml
<beans:beans>定義からデフォルトのxmlns="..."を削除する必要があることに注意してください。

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <security:http auto-config="true">
        <security:intercept-url pattern="/secured/**" access="ROLE_USER" />
        <security:form-login login-page="/login" default-target-url="/main"
                authentication-failure-url="/loginfailed" />
        <security:logout logout-success-url="/logout" />
    </security:http>

    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
                <security:user name="user" password="user" authorities="ROLE_USER" />
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>
</beans:beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd">

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.foo.webapp.WebAppConfig</param-value>
    </context-param>

    <!-- Spring Security -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>foo</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>foo</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
于 2013-01-22T21:53:08.213 に答える
1

SpringのJava構成を使用する場合のspringSecurityFilterChainに関する上記のヒントをありがとうございます。これらのヒントを適用して自分のコードの同等のエラーを修正してきたので、org.springframework.web.WebApplicationInitializer(AbstractAnnotationConfigDispatcherServletInitializerによって実装されたインターフェイス)のSpringドキュメントに次の関連する「警告」があることに気付きました。

web.xmlのバージョン管理

WEB-INF/web.xmlとWebApplicationInitializerの使用は相互に排他的ではありません。たとえば、web.xmlは1つのサーブレットを登録でき、WebApplicationInitializerは別のサーブレットを登録できます。初期化子は、ServletContext.getServletRegistration(String)などのメソッドを介してweb.xmlで実行される登録を変更することもできます。

ただし、WEB-INF / web.xmlがアプリケーションに存在する場合は、そのバージョン属性を「3.0」以上に設定する必要があります。そうしないと、サーブレットコンテナによってServletContainerInitializerブートストラップが無視されます。

上記のweb.xmlのバージョンがまだ2.5であることに気付いたので、これを指摘します。

于 2014-03-26T18:42:47.000 に答える
0

Spring3.2.3とサーブレット3.0で動作するようになりました。目盛りは、DelegatingFilterProxyクラスを拡張し、SpringSecurityFilterChainという名前を付けることです。

public class ServiceInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[] { ApplicationConfig.class };
}

@Override
protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[] { WebConfig.class };
}

@Override
protected String[] getServletMappings() {
    return new String[] { "/" };
}

@Override
protected Filter[] getServletFilters() {
    return new Filter[] { new OpenEntityManagerInViewFilter(), new SpringSecurityFilterChain() };
}

public class SpringSecurityFilterChain extends DelegatingFilterProxy {

}

}

于 2013-06-28T09:49:24.597 に答える