Announcement Announcement Module
Collapse
No announcement yet.
Case insensitive username Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Case insensitive username

    I would like to utilitize case insensitive usernames for authentication, but preserve the case in the actual user objects (and database) for display and logging purposes. I have implemented my own AuthenticationDao that finds the user in a case insensitive manner, and then always returns the same original case preserving username to Acegi. The only remaining "gotcha" that I'm aware of is the cache... Acegi uses the username as the cache key, which means that if the user enters a username with a different case than what is in the DB, then the user entered name won't match the cached name. Before I go extending the UserCache, I'm wondering if there is a better way I should approach this... or maybe a newer version of Acegi has already addressed this?

    Thanks,
    Andy

  • #2
    AuthenticationDao is meant to return the same case (for UserDetails.principal) as expressed in the database. The UserDetails.principal then gets used as the cache key, not the original String username. The UserDetails.principal also gets used in the Authentication that gets returned by DaoAuthenticationProvider, so the subsequent request for the same session should present the exact database-matching case for the principal.

    eg: We have a database with a username of "BenAlex". I try to login with "benalex". AuthenticationDao returns a UserDetails with a principal that should be "BenAlex". Then "BenAlex" gets stored in the UserCache as the key. Finally, "BenAlex" gets returned in the Authentication. When I next make a request, the ContextHolder will be re-populated with the "BenAlex" authentication, which will cache hit in DaoAuthenticationProvider as it's the same as the cache key.

    Am I missing something, or are you seeing different behaviour, Andy?

    Comment


    • #3
      This is all true, as you say, EXCEPT when it comes to the user cache and the case where the user (or client system) is logging in. The system will use the username, as entered by the user, to perform the cache lookup. The cache lookup will miss since, as far as I can tell, the cache lookup is a simple hashmap-like lookup that uses a case sensitive map (I'm not real familiar with EhCache yet, so I could be wrong here). In other words, if the user enters their username in a case different than what is in the DB, then the cache will miss and a DB hit will occur. Not a huge deal, but still something to consider.

      Thanks,
      Andy

      Comment


      • #4
        Originally posted by adepue
        The system will use the username, as entered by the user, to perform the cache lookup.
        The one and only time the username manually entered by the username will be used is when AuthenticationProcessingFilter.attemptAuthenticati on(HttpServletRequest) is called. The abstract parent coordinates workflow as follows:

        Code:
                    Authentication authResult;
        
                    try {
                        authResult = attemptAuthentication(httpRequest);
                    } catch (SomeStuff .....)
                    }
                        httpRequest.getSession().setAttribute(ACEGI_SECURITY_LAST_EXCEPTION_KEY,
                            failed);
                        httpRequest.getSession().removeAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY);
                        httpResponse.sendRedirect(httpResponse.encodeRedirectURL(httpRequest
                                .getContextPath() + failureUrl));
        
                        return;
                    }
        
                    // Authentication success
                    if (logger.isDebugEnabled()) {
                        logger.debug("Authentication success: " + authResult.toString());
                    }
                    httpRequest.getSession().setAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY,
                        authResult);
        As shown, the Authentication returned from DaoAuthenticationProvider (which should contain the CORRECT case for its principal, indeed its principal is more often than not the UserDetails instance) and that should be used on subsequent requests (as HttpSessionIntegrationFilter will obtain the stored Authentication from HttpSession and put it into ContextHolder on each request). The case originally used by the user to login (via AbstractProcessingFilter) should never be presented a second time.

        If you believe there's a problem Andy, would you please tell me which class(es) it's in so I can try to follow.

        Comment

        Working...
        X