环境:
- spring-xxx-3.1.0-Release 用于所有与 spring 相关的依赖项
- Java 1.6
- 雄猫 6
我已经实现了 Spring 安全性并且正在使用注释驱动的方法。一切似乎都已正确配置,但是当 SwitchUserFilter attemptSwitchUser 方法执行时,userDetailsService 始终为空。当我启动 tomcat 时,我可以使用调试器单步执行此类,并且 userDetailsService 不为空。但是,当我手动调用尝试开关用户方法时,userDetailsService 始终为空。这是我的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 时,userDetailsService 始终为空。在我看来,当过滤器运行时它没有被注入,但是从我看到的所有示例中正确地在 SwitchUserProcessingFilter 中引用了它。我已经搜索并找不到任何线索。提前感谢您的任何想法或建议。