Jetty 嵌入式服务器和 Spring 安全集成

Jetty Embedded Server and Spring Security integration

我正在尝试使用 Spring 安全登录,我的代码在使用 jetty maven 插件时有效。但现在我希望它在 运行 时也能在 Jetty Embedded Server 上工作。当我将登录提交到 spring 安全处理 link 时,它显示此警告:

HTTP ERROR: 500
INTERNAL_SERVER_ERROR
RequestURI=/auth/login_check
Caused by:
java.lang.AbstractMethodError
at javax.servlet.http.HttpServletRequestWrapper.changeSessionId(HttpServletRequestWrapper.java:290)
at javax.servlet.http.HttpServletRequestWrapper.changeSessionId(HttpServletRequestWrapper.java:290)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:209)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:194)
at org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy.applySessionFixation(ChangeSessionIdAuthenticationStrategy.java:48)
at org.springframework.security.web.authentication.session.AbstractSessionFixationProtectionStrategy.onAuthentication(AbstractSessionFixationProtectionStrategy.java:82)
at org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy.onAuthentication(ChangeSessionIdAuthenticationStrategy.java:32)
at org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy.onAuthentication(CompositeSessionAuthenticationStrategy.java:83)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:216)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:361)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:534)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:879)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:741)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:213)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:403)
at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:522)

我猜它与 Jetty 的 jsp-2.1、jsp-api-2.1 jar 冲突。我能做些什么来解决这个问题?这是我的码头依赖:

<properties>
    <jetty.version>6.1.14</jetty.version>
</properties>
...
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty</artifactId>
        <version>${jetty.version}</version>
    </dependency>
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-util</artifactId>
        <version>${jetty.version}</version>
    </dependency>
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-plus</artifactId>
        <version>${jetty.version}</version>
    </dependency>

    <!--jsp support for jetty, add the 2 following -->
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jsp-2.1</artifactId>
        <version>${jetty.version}</version>
    </dependency>
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jsp-api-2.1</artifactId>
        <version>${jetty.version}</version>
    </dependency>

Spring 调度程序 servlet 中的安全配置 xml:

<security:http auto-config="true" use-expressions="true">
    <security:form-login login-page="/login"
        username-parameter="email" password-parameter="password"
        login-processing-url="/auth/login_check" authentication-failure-url="/login?error"
        default-target-url="/" always-use-default-target="true" />
    <security:logout logout-url="/logout"
        logout-success-url="/" delete-cookies="JSESSIONID" />
    <security:remember-me token-validity-seconds="1209600"
        remember-me-parameter="remember-me" data-source-ref="dataSource" />
</security:http>

<security:authentication-manager>
    <security:authentication-provider>
        <security:password-encoder hash="md5" />
        <security:jdbc-user-service
            data-source-ref="dataSource"
            users-by-username-query="select email, password, enabled from users where email=?"
            authorities-by-username-query="select username, role from user_roles where username=?" />
    </security:authentication-provider>
</security:authentication-manager>

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://localhost:3306/chamgroupdb" />
    <property name="username" value="root"></property>
    <property name="password" value=""></property>
</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.DerbyDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="javax.persistence.validation.factory">validator</prop>
        </props>
    </property>
    <property name="packagesToScan" value="com.chamgroup.model" />
</bean>

您需要升级 Jetty 才能正常工作。

javax.servlet.http.HttpServletRequest.changeSessionId() 是在 Servlet 3.1 中引入的。

Jetty 6 是 Servlet 2.4 - 并在 2010 年 EOL(生命周期结束)

Jetty 7 是 Servlet 2.5 - 并于 2014 年停产

Jetty 8 是 Servlet 3.0 - 并于 2014 年停产

Jetty 9.0 - 9.1 是基于 Servlet 3.1 规范

早期 draft/alpha/beta 版本的版本

Jetty 9.2.x 是第一个支持最终 Servlet 3.1 规范的版本

Jetty 9.3.2 是 Jetty 的当前稳定版本(并且需要 Java 8)