Leejoy
Leejoy

Reputation: 1446

Spring security authentication fails

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

Answers (3)

Efe Kahraman
Efe Kahraman

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

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

Vyacheslav Shylkin
Vyacheslav Shylkin

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

Related Questions