1

环境:

  • spring-xxx-3.1.0-Release 用于所有与 spring 相关的依赖项
  • Java 1.6
  • 雄猫 6

我已经实现了 Spring 安全性并且正在使用注释驱动的方法。一切似乎都已正确配置,但是当 SwitchUserFilter attemptSwitchUser 方法执行时,userDetailsS​​ervice 始终为空。当我启动 tomcat 时,我可以使用调试器单步执行此类,并且 userDetailsS​​ervice 不为空。但是,当我手动调用尝试开关用户方法时,userDetailsS​​ervice 始终为空。这是我的xml配置:

applicationContext-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<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"
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 auto-config="true" use-expressions="true">
    <form-login login-page="/login.do" default-target-url="/dashboard.do" authentication-failure-url="/login.do?login_error=true" />
    <intercept-url pattern="/login.do" access="permitAll" />

    <!-- ADMIN -->
    <intercept-url pattern="/viewRoles.do" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/createNewRole.do" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/viewOrgs.do" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/j_spring_security_switch_user"     access="hasRole('ROLE_ADMIN')" />

    <session-management>
        <concurrency-control max-sessions="2" />
    </session-management>       
</http>

<authentication-manager>
    <authentication-provider user-service-ref="userDetailsService">
        <password-encoder hash="md5" />
    </authentication-provider>
</authentication-manager>
</b:beans>

应用程序上下文.xml:

<?xml version="1.0" encoding="UTF-8"?>

xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd            
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd">

<jpa:repositories base-package="com.vitaminj.repository" />

<context:annotation-config></context:annotation-config>

<context:component-scan base-package="com.vitaminj"></context:component-scan>

<mvc:annotation-driven />

<context:property-placeholder location="classpath:config.properties"></context:property-placeholder>

<bean class="org.springframework.context.support.ResourceBundleMessageSource"
    id="messageSource" p:basename="Messages">
</bean>

<!--  File Uploads  -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- Max size in bytes. -->
    <property name="maxUploadSize" value="16777215"/>
</bean>

<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
    id="dataSource" p:driverClassName="${jdbc.driverClassName}"
    p:password="${jdbc.password}" p:url="${jdbc.url}" p:username="${jdbc.username}">
</bean>

<bean class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
    id="sessionFactory">
    <property name="dataSource" ref="dataSource"></property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
        </props>
    </property>
    <property name="packagesToScan" value="com.vitaminj"></property>
</bean>

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    p:persistenceXmlLocation="classpath*:META-INF/persistence.xml"
    p:persistenceUnitName="vitaminJPersistence" p:dataSource-ref="dataSource"
    p:jpaVendorAdapter-ref="hibernateVendor" />

<bean id="hibernateVendor"
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    p:showSql="false" />

<!-- <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="persistenceUnitName" value="vitaminJPersistence" /> <property 
    name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" 
    /> <property name="loadTimeWeaver"> <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" 
    /> </property> </bean> -->

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<tx:annotation-driven />

<bean id="switchUserProcessingFilter" class="org.springframework.security.web.authentication.switchuser.SwitchUserFilter">

    <property name="userDetailsService" ref="userDetailsService" />
    <property name="switchUserUrl" value="/j_spring_security_switch_user" />
    <property name="exitUserUrl" value="/j_spring_security_exit_user" />
    <property name="targetUrl" value="/dashboard.do" />
</bean>

<!-- <bean id="ajaxTimeoutRedirectFilter" class="com.vitaminj.web.filter.AjaxTimeoutRedirectFilter">

</bean> -->

<!-- Begin Quartz config -->    
<bean class="com.vitaminj.quartz.QuartzJobSchedulingListener"></bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="jobFactory">
        <bean class="com.vitaminj.quartz.SpringQuartzJobFactory"></bean>
    </property>
</bean>

</beans>

jsp:

<form action='j_spring_security_switch_user' method='POST'>
 Switch to user: <input type='text' name='j_username' value='builderbob'/> <br/>
  <input type='submit' value='Switch'/>
</form>

我错误地遗漏了 web.xml。SwitchUserFilter 实际上正在被调用。

<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>companyname</display-name>
<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<session-config>
    <session-timeout>60</session-timeout>
</session-config>

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

<listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        classpath:applicationContext.xml
        classpath:applicationContext-security.xml
    </param-value>
</context-param>

<error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/jsp/404.jsp</location>
</error-page>


<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>

<filter>
    <filter-name>switchUserProcessingFilter</filter-name>
    <filter-class>org.springframework.security.web.authentication.switchuser.SwitchUserFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>switchUserProcessingFilter</filter-name>
    <url-pattern>/j_spring_security_switch_user</url-pattern>
</filter-mapping>

<filter>
    <filter-name>sitemesh</filter-name>
    <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>sitemesh</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<filter>
    <filter-name>openSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>

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

毫无疑问,在 SwitchUserFilter 的第 209 行中,在将表单提交到 j_spring_security_switch_user 时,userDetailsS​​ervice 始终为空。在我看来,当过滤器运行时它没有被注入,但是从我看到的所有示例中正确地在 SwitchUserProcessingFilter 中引用了它。我已经搜索并找不到任何线索。提前感谢您的任何想法或建议。

4

1 回答 1

3

Spring Security filters are not meant to be used directly in the web.xml. Quickly read through section 8.1 and 8.2 of the reference docs that describe how the Security Filter Chain is set up. You will need something like the following in your spring security config:

<!-- declare the filter bean -->
<beans:bean id="switchUserFilter" class="org.springframework.security.web.authentication.switchuser.SwitchUserFilter">
    <beans:property name="userDetailsService" ref="userDetailsService" />
    <beans:property name="switchUserUrl" value="/j_spring_security_switch_user" />
    <beans:property name="exitUserUrl" value="/j_spring_security_exit_user" />
    <beans:property name="targetUrl" value="/" />
</beans:bean>

<!-- include it in the security filter chain -->
<http auto-config="true" use-expressions="true">
    ...
    <custom-filter ref="switchUserFilter" position="SWITCH_USER_FILTER"/>
</http>
于 2013-06-28T20:45:41.667 回答