Reputation: 1446
I am using Spring security version 3.1.4.RELEASE. When I try to login to the application I am getting an error. I have cross checked the credentials in DB. Even though the credentials are correct the system is not lettng me to login. Following the details of error and my configuration settings.
Getting following error while trying to login to the system:
web.security.auth.CustomUsernamePasswordAuthenticationFilter username is support
web.security.auth.CustomUsernamePasswordAuthenticationFilter password is [PROTECTED]
web.security.auth.CustomUsernamePasswordAuthenticationFilter authRequest is org.springframework.security.authentication.UsernamePasswordAuthenticationToken@4a159a52: Principal: support; Credentials: [PROTECTED]; Authenticated: false; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 204.238.52.177; SessionId: 9B49838B0DF4224E169EAF425C0AABE9; Not granted any authorities
web.security.auth.CustomUsernamePasswordAuthenticationFilter Authentication manager was com.sun.proxy.$Proxy476
System.out loadUserByUsername support enter
org.springframework.security.authentication.event.LoggerListener Authentication event AuthenticationFailureServiceExceptionEvent: support; details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 204.238.52.177; SessionId: 9B49838B0DF4224E169EAF425C0AABE9; exception: null
Here I am getting the exception as null!
Config:
<authentication-manager alias="authenticationManager">
<authentication-provider ref="daoAuthenticationProvider" />
</authentication-manager>
<beans:bean id="plaintextPasswordEncoder" class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder" />
<beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="daoUserDetailsService" />
<beans:property name="passwordEncoder" ref="plaintextPasswordEncoder" />
</beans:bean>
<beans:bean id="daoUserDetailsService" class="web.security.auth.DAOUserDetailsService">
<beans:property name="dataSource" ref="dataSource" />
</beans:bean>
<beans:bean id="dataSource" class="web.security.auth.DAODataSource" />
<beans:bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<filter-chain-map request-matcher="ant">
<filter-chain pattern="/**" filters="channelProcessingFilter, SecurityContextPersistenceFilter, logoutFilter, authenticationFilter, anonymousAuthFilter, exceptionTranslationFilter, filterSecurityInterceptor" />
</filter-chain-map>
</beans:bean>
<beans:bean id="channelProcessingFilter" class="org.springframework.security.web.access.channel.ChannelProcessingFilter">
<beans:property name="channelDecisionManager" ref="channelDecisionManager"/>
<beans:property name="securityMetadataSource">
<filter-security-metadata-source request-matcher="ant">
<intercept-url pattern="/**" access="REQUIRES_SECURE_CHANNEL"/>
</filter-security-metadata-source>
</beans:property>
</beans:bean>
<beans:bean id="channelDecisionManager" class="org.springframework.security.web.access.channel.ChannelDecisionManagerImpl">
<beans:property name="channelProcessors">
<beans:list>
<beans:ref bean="secureChannelProcessor"/>
<beans:ref bean="insecureChannelProcessor"/>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="secureChannelProcessor" class="org.springframework.security.web.access.channel.SecureChannelProcessor" />
<beans:bean id="insecureChannelProcessor" class="org.springframework.security.web.access.channel.InsecureChannelProcessor" />
<beans:bean id="SecurityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />
<beans:bean id="authenticationFilter" class="web.security.auth.CustomUsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="filterProcessesUrl" value="/j_spring_security_check"/>
<beans:property name="usernameParameter" value="username"/>
<beans:property name="passwordParameter" value="password"/>
</beans:bean>
<beans:bean id="anonymousAuthFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<beans:property name="key" value="foobar"/>
<beans:property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</beans:bean>
<beans:bean id="anonymousAuthenticationProvider" class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
<beans:property name="key" value="foobar"/>
</beans:bean>
<beans:bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="accessDecisionManager" ref="accessDecisionManager"/>
<beans:property name="securityMetadataSource">
<filter-security-metadata-source>
<intercept-url pattern="/LoginPage" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/LoginExpiredPage" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/wicket/bookmarkable/web.sec.pages.LoginExpiredPage" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/css/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/images/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/*.png" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/*.ico" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/wicket/resource/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY, IS_AUTHENTICATED_REMEMBERED"/>
</filter-security-metadata-source>
</beans:property>
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:bean class="org.springframework.security.access.vote.RoleVoter">
<beans:property name="rolePrefix" value="ROLE_"/>
</beans:bean>
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg value="/" />
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</beans:list>
</beans:constructor-arg>
<beans:property name="filterProcessesUrl" value="/logout"/>
</beans:bean>
<beans:bean id="forceCookieUseFilter" class="web.security.ForceCookieUseFilter">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<beans:property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
<beans:property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</beans:bean>
<beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/LoginPage"/>
</beans:bean>
<beans:bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<beans:property name="errorPage" value="/accessDenied.htm"/>
</beans:bean>
<beans:bean id="loggerListener" class="org.springframework.security.authentication.event.LoggerListener"/>
AuthenticationFilter class as follows:
public class CustomUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private boolean postOnly = true;
public CustomUsernamePasswordAuthenticationFilter() {
super("/j_spring_security_check");
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
if(this.getAuthenticationManager()==null){
logger.info("Authentication manager is null.");
} else {
logger.info("Authentication manager was "+this.getAuthenticationManager().getClass().getName());
}
return this.getAuthenticationManager().authenticate(authRequest);
}
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
public void setUsernameParameter(String usernameParameter) {
this.usernameParameter = usernameParameter;
}
public void setPasswordParameter(String passwordParameter) {
this.passwordParameter = passwordParameter;
}
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
public final String getUsernameParameter() {
return usernameParameter;
}
public final String getPasswordParameter() {
return passwordParameter;
}
}
UserDetails class as follows:
public class DAOUserDetailsService implements UserDetailsService {
private DataSource dataSource;
public void setDataSource(DAODataSource dataSource) {
this.dataSource = dataSource;
}
public DAOUserDetailsService () { }
public DAOUserDetailsService (DAODataSource dataSource) {
this.dataSource = dataSource;
}
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
DataSource ds = dataSource;
PreparedStatement userStatement = null;
try {
Connection con = ds.getConnection();
String userQuery = "SELECT USER_ID, USER_PASSWORD, USER_ENABLED FROM USER WHERE USER_ID = ?";
userStatement = con.prepareStatement(userQuery);
userStatement.setString(0, username);
ResultSet userResults = userStatement.executeQuery();
if (userResults.next()) {
final SimpleGrantedAuthority supervisorAuthority = new SimpleGrantedAuthority(
"supervisor");
final SimpleGrantedAuthority userAuthority = new SimpleGrantedAuthority(
"user");
Collection<GrantedAuthority> authorityList = new ArrayList<GrantedAuthority>();
authorityList.add(supervisorAuthority);
authorityList.add(userAuthority);
return new User(userResults.getString(0), userResults.getString(1), authorityList);
}
throw new UsernameNotFoundException(username);
} catch (SQLException e) {
throw new UsernameNotFoundException(e.toString());
}
finally {
if (userStatement != null) {
try {
userStatement.close();
} catch (SQLException e) {
throw new UsernameNotFoundException(e.toString());
}
}
}
}
}
Kindly provide some idea on the issue. Thanks in advance.
Upvotes: 3
Views: 2688
Reputation: 1438
You have to add ROLE_
prefix to role while creating your GrantedAuthority
. So you code should look like:
// For xxx
final SimpleGrantedAuthority supervisorAuthority = new SimpleGrantedAuthority(
"ROLE_xxx");
Alternative: You can clear default prefix in RoleVoter
but IMO this is not a good choice because ROLE_ prefix actually helps RoleVoter
to understand what remaning string is.
<bean id="roleVoter" class="org.springframework.security.vote.RoleVoter">
<property name="rolePrefix" value=""></property>
</bean>
Upvotes: 2
Reputation: 349
You can create your implementation of LoggerListener for investigate more the causes.
public class LoggerListener implements ApplicationListener<AbstractAuthorizationEvent> {
private static final Log logger = LogFactory.getLog(LoggerListener.class);
public void onApplicationEvent(AbstractAuthorizationEvent event) {
//investigation code
}
}
I had a very similar problem and the cause was one ClassCastException in other part of code, one controller.
Upvotes: 4
Reputation: 9801
In your class DAOUserDetailsService:
...
return new User(userResults.getString(0), userResults.getString(1), new ArrayList<GrantedAuthority>());
...
you return UserDeatils with empty authorities. So your user is loged in but he has no roles (not authorised).
Upvotes: 3