Spring security authentication: get username without SPRING_SECURITY_LAST_USERNAME

11,839

Solution 1

The documentation of the deprecated constant tells exactly what you should do:

/**
 * @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler}
 */
@Deprecated
public static final String SPRING_SECURITY_LAST_USERNAME_KEY =
           "SPRING_SECURITY_LAST_USERNAME";

Something like this:

public class UserNameCachingAuthenticationFailureHandler
    extends SimpleUrlAuthenticationFailureHandler {

    public static final String LAST_USERNAME_KEY = "LAST_USERNAME";

    @Autowired
    private UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter;

    @Override
    public void onAuthenticationFailure(
            HttpServletRequest request, HttpServletResponse response,
            AuthenticationException exception)
            throws IOException, ServletException {

        super.onAuthenticationFailure(request, response, exception);

        String usernameParameter =
            usernamePasswordAuthenticationFilter.getUsernameParameter();
        String lastUserName = request.getParameter(usernameParameter);

        HttpSession session = request.getSession(false);
        if (session != null || isAllowSessionCreation()) {
            request.getSession().setAttribute(LAST_USERNAME_KEY, lastUserName);
        }
    }
}

In your security config:

<security:http ...>
    ...
    <security:form-login
        authentication-failure-handler-ref="userNameCachingAuthenticationFailureHandler"
    ...
    />
</security:http>

<bean 
    id="userNameCachingAuthenticationFailureHandler"
    class="so.UserNameCachingAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/url/to/login?error=true"/>
</bean>

In your login.jsp:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="true" %>

...

<%--in the login form definition--%>
<input id="j_username" name="j_username" type="text" 
    value="<c:out value="${sessionScope.LAST_USERNAME}"/>"/>

Solution 2

If anyone comes here who is having this problem in Grails Spring security. You can now use the following-

import grails.plugin.springsecurity.SpringSecurityUtils;

Now use SpringSecurityUtils.SPRING_SECURITY_LAST_USERNAME_KEY this will work and is not deprecated.

Share:
11,839
droidpl
Author by

droidpl

Updated on June 05, 2022

Comments

  • droidpl
    droidpl about 2 years

    I'm new at spring framework. I'm creating a login page for my webapp and I want the user to login before any action on the app. If the user enters good credentials everything it's ok and working, but if enters bad ones I want to display a message and keep the username on the input element. Displaying a message is not a problem, but I'm not able to keep the username in my jps file without using the deprecated variable SPRING_SECURITY_LAST_USERNAME.

    Hope someone can help me, I'm using Spring 3.

    UPDATE: the requirements says I don't want to display the username on the url.

  • zagyi
    zagyi over 11 years
    No problem. Note that there is space for improvement at some points. E.g. hard-coding the session attribute's name in the .jsp is not elegant. Ideally it should refer to the constant defined in UserNameCachingAuthenticationFailureHandler. (I have to admint I don't know how to achieve this indirection.)
  • droidpl
    droidpl over 11 years
    I didn't know this could be achieved! But for now that's all I need, this not security properly but a little trick to make the user life better! It's incredible that I coudn't find another simple solution like this anywhere! ;)
  • Jason
    Jason almost 11 years
    is it just me, or is that a crap load of code just to keep the username input on the form?
  • AxeEffect
    AxeEffect almost 10 years
    request.getParameter("j_username") can also be called successfully from the RedirectStrategy.sendRedirect() method if you're implementing it as a customised bean (actually this bean is a member variable/field of the AuthenticationFailureHandler class/bean).
  • Jonathas Pacífico
    Jonathas Pacífico over 7 years
    usernamePasswordAuthenticationFilter is null. Spring Security 4. How can I solve this?
  • Bassam
    Bassam over 7 years
    I have added the line @Autowired UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter; but I am getting the error no qualifying bean UsernamePasswordAuthenticationFilter I am using Spring security 4.2.0 and MVC.
  • Bassam
    Bassam over 7 years
    How can this possibly work? The filter chain creates the usernamePasswordAuthenticationFilter. But to create the filter chain, we need the handler. But the handler depends on the filter which has not been created yet. I don't this works in Spring 4
  • Amir
    Amir over 2 years
    how to create bean of UsernamePasswordAuthenticationFilter and specified AuthenticationManager?