【发布时间】:2014-08-22 05:05:21
【问题描述】:
我知道有一些关于这个话题的问题,但我的有点不同。我正在尝试将 openID 身份验证包含在使用 Spring、Spring-security 和 Spring-MVC 开发的项目中。
要实现openID auth,需要一些类:在applicationContext-security.xml中配置AccessDeniedHandler和UserDetailsService:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:security="http://www.springframework.org/schema/security"
xmlns="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">
<!-- turn on global security -->
<security:global-method-security secured-annotations="enabled"/>
<bean id="openIdAuthFailureHandler" class="es.institution.dept.security.MyAccessDeniedHandler"/>
<bean id="userDetailsService" class="es.institution.dept.service.impl.UserDetailsServiceImpl"/>
<security:http auto-config="true">
<security:intercept-url pattern="/welcome*" access="ROLE_USER, ROLE_ADMIN" />
<security:intercept-url pattern="/user/*" access="ROLE_USER, ROLE_ADMIN" />
<security:intercept-url pattern="/rest/*" access="ROLE_USER, ROLE_ADMIN" />
<security:intercept-url pattern="/admin/*" access="ROLE_ADMIN" />
<security:logout logout-success-url="/" />
<security:openid-login login-page="/openidLogin" default-target-url="/welcome" authentication-failure-url="/loginfailed" user-service-ref="userDetailsService"/>
<security:access-denied-handler ref="openIdAuthFailureHandler"/>
</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 username, password, active as enabled
FROM users WHERE username=?"
authorities-by-username-query="
select ur.username, ur.rolename as authority from users_roles ur
where ur.username=?" />
</security:authentication-provider>
</security:authentication-manager>
</beans>
Spring 在需要知道用户数据(用户名、密码、角色...)时调用 UserDetailsService。因此,我需要在 UserDetailsService 中调用我的服务之一(UserService):
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
UserService userService;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
es.institution.dept.model.User user = userService.getUserByUsername("mannuk");
if(user == null)
throw new UsernameNotFoundException("User does not exist");
return new User(user.getUsername(), user.getPassword(), user.isActive(), false, false, false, getGrantedAuthorities(username));
}
public List<GrantedAuthority> getGrantedAuthorities(String username) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (Role role : userService.getAllRoles(username)) {
authorities.add(new SimpleGrantedAuthority(role.getRoleName()));
}
return authorities;
}
}
我尝试了两种选择:
1) 在 UserDetailsService 中定义 @Service 注解,它会在启动期间抛出异常。它说 UserDetails bean 不存在(在 applicationSecurity-context.xml 中是必需的)
2) 在 applicationContext-security.xml 中声明一个 bean 定义。启动正常(没有错误),但 UserService 没有自动装配。
这是我的 applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/adminDB"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="/WEB-INF/mybatis-config.xml" />
</bean>
<bean id="usersMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.institution.dept.dao.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="rolesMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.institution.dept.dao.RoleMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="groupMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.institution.dept.dao.GroupMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="policyMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.institution.dept.dao.PolicyMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<!-- Json converter bean -->
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper"></bean>
</beans>
这是我的 app-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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:task="http://www.springframework.org/schema/task"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-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/task http://www.springframework.org/schema/task/spring-task-3.1.xsd">
<!-- Enabling Spring beans auto-discovery -->
<context:component-scan base-package="es.institution.dept" />
<!-- Enabling Spring MVC configuration through annotations -->
<mvc:annotation-driven />
<!-- Enabling Spring Async tasks through annotations -->
<task:annotation-driven />
<mvc:view-controller path="/" view-name="login" />
<!-- Load resources -->
<mvc:resources mapping="/resources/**" location="/resources/"/>
<!-- Bean definitions i18n -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
<!-- Intercepts the change of the locale: example.html?ln=en -->
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="ln" />
</bean>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" >
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor" />
</list>
</property>
</bean>
<!-- Register the messages.properties -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="WEB-INF/classes/locale/messages" />
</bean>
<!-- Defining which view resolver to use -->
<bean class= "org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
请注意,UserService 在控制器等其他地方运行良好。这似乎是 UserDetailsService 本身的问题。
如果您需要更多信息,请随时给我写信。我希望能解决这个问题。解决方案将被投票和检查。
【问题讨论】:
标签: spring spring-mvc spring-security