我已经编写了自定义UserDetailsService来验证来自数据库的用户。第一次它工作正常但是当同一用户尝试登录后第二次登出时它给出了错误。我的应用程序基于 Spring 3.1,Spring安全与tomcat 7上的漂亮面孔
org.springframework.security.authentication.BadCredentialsException: Bad credentials
这是我的配置详细信息web.xml
<?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"
version="2.5" metadata-complete="true">
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/application-context.xml,
/WEB-INF/spring/application-context-security.xml
</param-value>
</context-param>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>redmond</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<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-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/application-context.xml,
/WEB-INF/spring/application-context-security.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/jcsb</url-pattern>
</servlet-mapping>
<!-- Pretty Face -->
<filter>
<filter-name>Pretty Filter</filter-name>
<filter-class>com.ocpsoft.pretty.PrettyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Pretty Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>org.springframework.security.access.AccessDeniedException</exception-type>
<location>/login.xhtml</location>
</error-page>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/index.html</location>
</error-page>
应用context.xml中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:component-scan base-package="com.swift.jcbs.web" />
<tx:annotation-driven />
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="view">
<bean class="com.suraj.jcbs.web.spring.ViewScope"/>
</entry>
</map>
</property>
</bean>
应用程序上下文的security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:faces="http://www.springframework.org/schema/faces"
xmlns:int-security="http://www.springframework.org/schema/integration/security"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/integration/security http://www.springframework.org/schema/integration/security/spring-integration-security-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/faces http://www.springframework.org/schema/faces/spring-faces-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<sec:global-method-security
secured-annotations="enabled" jsr250-annotations="enabled" pre-post-annotations="enabled">
</sec:global-method-security>
<!--
resource security
Note:
Access-denied-page is invoked when user is AUTHENTICATED but is not AUTHORIZED to access protected resources.
When user is NOT AUTHENTICATED, he is moved into form-login instead of access-denied-page.
-->
<sec:http access-denied-page="/access_denied.xhtml" use-expressions="true" auto-config="true" >
<sec:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:form-login login-page="/login.jsf"/>
<sec:intercept-url pattern="/secured/**" access="isAuthenticated()"/>
<sec:intercept-url pattern="/WEB-INF/faces/**" access="isAuthenticated()"/>
<sec:logout logout-url="/logout" logout-success-url="/secured/home" delete-cookies="JSESSIONID" />
<sec:session-management invalid-session-url="/secured/home">
<sec:concurrency-control error-if-maximum-exceeded="true" max-sessions="6"/>
</sec:session-management>
</sec:http>
<!--
manager responsible for loading user account with assigned roles
-->
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider
user-service-ref="userVerificationService"/>
</sec:authentication-manager>
@Service
public class UserVerificationService implements UserDetailsService {
private HashMap<String, org.springframework.security.core.userdetails.User> users = new HashMap<String, org.springframework.security.core.userdetails.User>();
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
org.springframework.security.core.userdetails.User user = users.get(username);
if (user == null) {
throw new UsernameNotFoundException("UserAccount for name \""
+ username + "\" not found.");
}
return user;
}
@PostConstruct
public void init() {
// sample roles
Collection<GrantedAuthority> adminAuthorities = new ArrayList<GrantedAuthority>();
adminAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
Collection<GrantedAuthority> userAuthorities = new ArrayList<GrantedAuthority>();
adminAuthorities.add(new SimpleGrantedAuthority("ROLE_REGISTERED"));
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
// sample users with roles set
users.put("admin", new org.springframework.security.core.userdetails.User("admin", "admin", enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, adminAuthorities));
users.put("user", new org.springframework.security.core.userdetails.User("user", "user", enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, userAuthorities));
}
@Service
public class AuthenticationServiceImpl implements AuthenticateService {
@Resource(name = "authenticationManager")
private AuthenticationManager authenticationManager;
public boolean login(String username, String password) {
try {
System.out.println("inside login");
System.out.println("AuthenticationServiceImpl user name " +username +" Pass = "+password);
Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
username, password));
SecurityContextHolder.getContext().setAuthentication(authenticate);
HttpUtils.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
return true;
} catch (AuthenticationException e) {
e.printStackTrace();
}
return false;
}
这是我的loginBean
public String process() {
System.out.println("user name " + username + " Pass = " + password);
if (authenticateService.login(username, password)) {
return "pretty:home";
} else {
FacesUtils.addErrorMessage("Invalid UserName or Password");
return null;
}
}
答案 0 :(得分:5)
从Spring 3.1开始,User Credentials are being erased通常会导致一些问题。我通过关闭上述功能解决了这个问题。
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<property name="eraseCredentialsAfterAuthentication" value="false"/>
</bean>
如果您使用的是名称空间,则可以使用
<authentication-manager erase-credentials="false">