2017-09-14 143 views
0

有没有人成功地将RestEASY与Spring Security和Spring Session集成?我遇到了ContextLoadListener的问题。我能够将RestEASY和Spring Security与以下web.xml集成。RestEASY,Spring Security,Spring Session集成

<web-app> 
<display-name>Admin Service</display-name> 
<context-param> 
    <param-name>resteasy.servlet.mapping.prefix</param-name> 
    <param-value>/admin</param-value> 
</context-param> 
<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.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> 
</listener> 
<listener> 
    <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class> 
</listener> 
<servlet> 
    <servlet-name>AdminService</servlet-name> 
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> 
    <init-param> 
     <param-name>javax.ws.rs.Application</param-name> 
     <param-value>com.etouchpoint.admin.service.AdminApplication</param-value> 
    </init-param> 
</servlet> 
<servlet-mapping> 
    <servlet-name>AdminService</servlet-name> 
    <url-pattern>/admin/*</url-pattern> 
</servlet-mapping> 

阅读文档的春季会议后,在web.xml最终会看起来像这样:

<web-app> 
<display-name>Admin Service</display-name> 

<!-- Context for Spring HttpSession --> 
<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/spring/session.xml</param-value> 
</context-param> 

<!-- Context for RestEasy --> 
<context-param> 
    <param-name>resteasy.servlet.mapping.prefix</param-name> 
    <param-value>/admin</param-value> 
</context-param> 

<!-- Filter and Mapping for Spring Session --> 
<filter> 
    <filter-name>springSessionRepositoryFilter</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>springSessionRepositoryFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

<!-- Filter and Mapping for 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 for Spring Session --> 
<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

<!-- Listeners for RestEasy --> 
<listener> 
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> 
</listener> 
<listener> 
    <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class> 
</listener> 

<servlet> 
    <servlet-name>AdminService</servlet-name> 
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> 
    <init-param> 
     <param-name>javax.ws.rs.Application</param-name> 
     <param-value>com.etouchpoint.admin.service.AdminApplication</param-value> 
    </init-param> 
</servlet> 

<servlet-mapping> 
    <servlet-name>AdminService</servlet-name> 
    <url-pattern>/admin/*</url-pattern> 
</servlet-mapping> 

具有这种配置的问题是,有是2不允许的ContextLoadListeners。所以,我尝试创建一个源自Spring Security的类,并为其添加Spring Session和RestEASY Context Listeners。

会话配置:

@Configuration 
@EnableJdbcHttpSession 
public class SessionConfig { 
    @Bean 
    public PlatformTransactionManager transactionManager(final DataSource dataSource) { 
     return new DataSourceTransactionManager(dataSource); 
    }} 

ContextLoadListener:

public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer { 

public SecurityInitializer() { 
    super(SecurityConfig.class, SessionConfig.class, SpringContextLoaderListener.class); 
}} 

这也不起作用。你最终与此异常:

java.lang.NoSuchMethodException: org.springframework.security.access.SecurityConfig.<init>() 

我很茫然,此刻如何获得这3个库发挥很好。有没有人做过这个?什么是通用解决方案?你把所有东西都移到Java中,还是你能用XML来完成?

回答

0

终于搞明白了!

的web.xml

夫妇的事情,这里要注意。

  • 此配置适用于Servlet 3.0容器。因此,请遵循一些Restesy set up for Servlet 3.0 Containers
  • 即使使用Servlet 3.0容器,也可以使用org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap和org.jboss.resteasy.plugins.spring.SpringContextLoaderListener。不要使用org.springframework.web.context.ContextLoaderListener。请参阅Spring Integration for Resteasy
<?xml version="1.0" encoding="UTF-8"?> 
<web-app 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
    version="3.0"> 

    <display-name>Admin</display-name> 

    <!-- Filter for Spring Session --> 
    <filter> 
     <filter-name>springSessionRepositoryFilter</filter-name> 
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>springSessionRepositoryFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
     <dispatcher>REQUEST</dispatcher> 
     <dispatcher>ERROR</dispatcher> 
    </filter-mapping> 

    <!-- Filter for 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 for Resteasy --> 
    <listener> 
     <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> 
    </listener> 
    <listener> 
     <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class> 
    </listener> 

</web-app> 

的applicationContext.xml

<beans 
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation=" 
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"> 

    <!-- This context will contain all of the spring configs --> 
    <import resource="classpath:admin-context.xml" /> 

    <!-- This context will contain all of the spring session/security configs --> 
    <import resource="classpath:admin-security-context.xml" /> 

</beans> 

管理,安全的context.xml

<beans 
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:security="http://www.springframework.org/schema/security" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation=" 
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"> 

    <context:annotation-config/> 

    <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
     <constructor-arg ref="dataSource"/> 
    </bean> 

    <bean class="....CustomJdbcHttpSessionConfiguration" /> 

    <bean id="adminAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler"> 
     <property name="defaultTargetUrl" value="/index.html" /> 
     <property name="alwaysUseDefaultTargetUrl" value="true" /> 
     <property name="useReferer" value="true" /> 
    </bean> 

    <bean id="adminLoginFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> 
     <property name="defaultFailureUrl" value="/login.html" /> 
     <property name="forwardToDestination" value="true" /> 
    </bean> 

    <security:http pattern="/static/**" security="none" /> 
    <security:http pattern="/favicon.ico" security="none" /> 
    <security:http pattern="/robots.txt" security="none" /> 

    <security:http> 
     <security:csrf disabled="true"/> 

     <security:intercept-url pattern="/login.html" access="hasAnyRole('ANONYMOUS')" requires-channel="any" /> 
     <security:intercept-url pattern="/login" access="hasAnyRole('ANONYMOUS')" requires-channel="any" /> 

     <security:intercept-url pattern="/**" access="hasAnyRole('ADMIN')" requires-channel="any" /> 

     <!-- All of these parameters are needed for login to work correctly -->  
     <security:form-login login-page="/login.html" login-processing-url="/login" authentication-success-handler-ref="adminAuthenticationSuccessHandler" authentication-failure-handler-ref="adminLoginFailureHandler" username-parameter="username" password-parameter="password"/> 

     <!-- Change cookie name to 'SESSION' because that is what is used with Spring Session --> 
     <!-- And all parameters are needed --> 
     <security:logout logout-url="/logout" invalidate-session="true" delete-cookies="SESSION" logout-success-url="/login.html" /> 

    </security:http> 

    <security:authentication-manager> 
     <security:authentication-provider user-service-ref="userDetailsService"> 
      <security:password-encoder hash="sha" /> 
     </security:authentication-provider> 
    </security:authentication-manager> 

</beans> 

CustomJdbcHttpSessionConfiguration.java

这里创建一个自定义的对象,因此可以有多个应用程序部署 ,他们都使用相同的cookie。在这里要小心,因为这将 cookie设置为'/',这意味着如果Cookie需要有不同的域 ,则此自定义对象将覆盖域。

public class CustomJdbcHttpSessionConfiguration extends JdbcHttpSessionConfiguration { 

    @Bean 
    public CookieSerializer cookieSerializer() { 

     final DefaultCookieSerializer serializer = new DefaultCookieSerializer(); 
     serializer.setCookieName("SESSION"); // <1> 
     serializer.setCookiePath("/"); // <2> 
     serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$"); // <3> 

     return serializer; 
    } 

} 

AdminApplication.java

@ApplicationPath("service") 
public class AdminApplication extends Application { 

}