嵌入式Jetty身份验证

时间:2013-04-22 18:12:04

标签: java spring spring-mvc spring-security embedded-jetty

我正在尝试使用嵌入Jetty将摘要式身份验证添加到通过HTTP提供的API。我没有web.xml,这不是webapp。通过从我的文件“spring-config.xml”创建ClassPathXmlApplicationContext对象来启动应用程序。在“spring-config.xml”中,我为服务等定义了很多bean,还有一个bean来启动Jetty服务器。

Jetty服务器配置了DispatcherServlet(实际上是一个实现ApplicationContextAware的DispatcherServletWrapper类,并将ClassPathXmlApplicationContext对象设置为它创建的GenericWebApplicationContext的父对象,这样它可以访问我的spring-config.xml文件中定义的bean)

一切正常,失败的地方是尝试添加身份验证。我添加了所有spring-security配置来设置digest auth,但我不知道如何让Jetty知道过滤器链。

我的spring-config.xml的相关部分如下所示:

<bean id="restApiController" class="com.company.project.api.controllers.RESTfulController">
    <property name="broker" ref="broker"/>
</bean>

<mvc:annotation-driven/>

<!--++++++++++++++++++++++
     JETTY BEANS
+++++++++++++++++++++++-->

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider>
    <security:user-service id="userService">
        <security:user name="apiUser" password="apiPassword" authorities="ROLE_USER"/>
    </security:user-service>
</security:authentication-provider>
</security:authentication-manager>

<bean id="digestEntryPoint" class="org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
<property name="realmName" value="Digest Auth Realm"/>
<property name="key" value="acegi"/>
</bean>

<bean id="digestFilter" class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
<property name="userDetailsService" ref="userService"/>
<property name="authenticationEntryPoint" ref="digestEntryPoint"/>
</bean>

<security:http create-session="stateless" use-expressions="true" entry-point-ref="digestEntryPoint">
<security:intercept-url pattern="/**" access="ROLE_USER"/>
<security:custom-filter ref="digestFilter" position="FIRST"/>
</security:http>

<bean id="JettyServer" class="org.eclipse.jetty.server.Server" init-method="start" destroy-method="stop">

<constructor-arg>
        <bean id="threadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool">
            <property name="minThreads" value="2"/>
            <property name="maxThreads" value="10"/>
        </bean>
</constructor-arg>

<property name="connectors">
    <list>
        <bean id="Connector" class="org.eclipse.jetty.server.ServerConnector">
            <constructor-arg ref="JettyServer"/>
            <property name="port" value="8090"/>
        </bean>
    </list>
</property>

<property name="handler">
    <bean id="handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
        <property name="handlers">
            <list>
                <bean id="servletContextHandler" class="org.eclipse.jetty.servlet.ServletContextHandler">
                    <property name="contextPath" value="/"/>
                    <property name="servletHandler">
                        <bean class="org.eclipse.jetty.servlet.ServletHandler">
                            <property name="filters">
                                <list>
                                    <bean class="org.eclipse.jetty.servlet.FilterHolder">
                                        <property name="name" value="springSecurityFilterChain"/>
                                        <property name="filter">
                                            <bean class="org.springframework.web.filter.DelegatingFilterProxy"/>
                                        </property>
                                        <!--<property name="filter" ref="digestFilter"/>-->
                                    </bean>
                                </list>
                            </property>
                            <property name="filterMappings">
                                <list>
                                    <bean class="org.eclipse.jetty.servlet.FilterMapping">
                                        <property name="filterName" value="springSecurityFilterChain"/>
                                        <property name="pathSpec"><value>/*</value></property>
                                    </bean>
                                </list>
                            </property>
                            <property name="servlets">
                                <list>
                                    <bean class="org.eclipse.jetty.servlet.ServletHolder">
                                        <property name="name" value="DefaultServlet"/>
                                        <property name="servlet">
                                            <!--<bean class="org.springframework.web.servlet.DispatcherServlet"/>-->
                                            <bean class="com.impulse.sessiontracker.api.DispatcherServletWrapper"/>
                                        </property>
                                        <!--
                                        <property name="initParameters">
                                            <map>
                                                <entry key="contextConfigLocation" value="classpath:./spring-security.xml" />
                                            </map>
                                        </property>
                                        -->
                                    </bean>
                                </list>
                            </property>
                            <property name="servletMappings">
                                <list>
                                    <bean class="org.eclipse.jetty.servlet.ServletMapping">
                                        <property name="pathSpecs">
                                            <list><value>/</value></list>
                                        </property>
                                        <property name="servletName" value="DefaultServlet"/>
                                    </bean>
                                </list>
                            </property>
                        </bean>
                    </property>
                </bean>
                <bean class="org.eclipse.jetty.server.handler.RequestLogHandler">
                    <property name="requestLog">
                        <bean class="org.eclipse.jetty.server.NCSARequestLog">
                            <constructor-arg value="/opt/impulse/logs/jetty-yyyy_mm_dd.log"/>
                            <property name="extended" value="false" />
                        </bean>
                    </property>
                </bean>
            </list>
        </property>
    </bean>
</property>

</bean>

我尝试直接在jetty的过滤器列表中引用DigestAuthenticationFilter,这似乎不会导致任何事情发生。我已经尝试了上面显示的方法,其中我尝试引用DelegatingFilterProxy,这导致“ServletContext不能为空”异常。尝试并将其命名为“springSecurityFilterChain”是完整的猜测,基于一些spring-docs和我读过的其他问题。

有谁能告诉我如何获得Jetty使用的这些身份验证配置?我想做的事情有意义吗?

作为参考,我的DispatcherServletWrapper如下所示:

public class DispatcherServletWrapper extends DispatcherServlet implements ApplicationContextAware {

    private static final long serialVersionUID = -2281511575328213502L;
    private ApplicationContext appContext;

    @Override
    public void setApplicationContext(ApplicationContext arg0)
            throws BeansException {
        this.appContext = arg0; 
    }

    protected WebApplicationContext createWebApplicationContext(WebApplicationContext arg0) {
        GenericWebApplicationContext wac = new GenericWebApplicationContext();
        wac.setParent(appContext);
        wac.refresh();

        return wac;
    }

}

1 个答案:

答案 0 :(得分:2)

我已经成功配置了没有web.xml的嵌入式Jetty + spring-security

您可以以编程方式添加DelegatingFilterProxy并将其传递给目标bean名称“springSecurityFilterChain”

//Spring Security servlet
final FilterHolder springSecurityFilterChain = new FilterHolder(
    new DelegatingFilterProxy("springSecurityFilterChain"));

jettyServletContext.addFilterWithMapping(springSecurityFilterChain, "/*",
                              EnumSet.of(DispatcherType.REQUEST));

我也尝试使用DigestAuthenticationFilter,但这不起作用。

希望这可以帮到你。