views:

2970

answers:

1

I am relatively new to Spring and Spring security.

I was attempting to write a program where I needed to authenticate a user at the server end using Spring security,

I came up with the following:

public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider{
    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken)
                    throws AuthenticationException
    {
        System.out.println("Method invoked : additionalAuthenticationChecks isAuthenticated ? :"+usernamePasswordAuthenticationToken.isAuthenticated());
    }

    @Override
    protected UserDetails retrieveUser(String username,UsernamePasswordAuthenticationToken authentication) throws AuthenticationException 
    {
        System.out.println("Method invoked : retrieveUser");
        //so far so good, i can authenticate user here, and throw exception if not authenticated!!
        //THIS IS WHERE I WANT TO ACCESS SESSION OBJECT
    }
}

My usecase is that when a user is authenticated, I need to place an attribute like:

session.setAttribute("userObject", myUserObject);

myUserObject is an object of some class that I can access throughout my server code across multiple user requests.

+6  A: 

Your friend here is org.springframework.web.context.request.RequestContextHolder

// example usage
public static HttpSession session() {
    ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
    return attr.getRequest().getSession(true); // true == allow create
}

This will be populated by the standard spring mvc dispatch servlet, but if you are using a different web framework you have add org.springframework.web.filter.RequestContextFilter as a filter in your web.xml to manage the holder.

EDIT: just as a side issue what are you actually trying to do, I'm not sure you should need access to the HttpSession in the retieveUser method of a UserDetailsService. Spring security will put the UserDetails object in the session for you any how. It can be retrieved by accessing the SecurityContextHolder:

public static UserDetails currentUserDetails(){
    SecurityContext securityContext = SecurityContextHolder.getContext();
    Authentication authentication = securityContext.getAuthentication();
    if (authentication != null) {
        Object principal = authentication.getPrincipal();
        return principal instanceof UserDetails ? principal : null;
    }
    return null;
}
Gareth Davis
@first point:I tried using RequestContextHolder, it gave me an error:No thread-bound request found:Are you referring to ... use RequestContextListener or RequestContextFilter to expose the current request.I didnt try filters i guess, will try that and let u know if it works.@second point: actually its a custom object hence i didnt prefer UserDetailsif possible do see my other question on similar topic:http://stackoverflow.com/questions/1629273/is-it-possible-to-send-more-data-in-form-based-authentication-in-spring
Salvin Francis
if you are not using the dispatch servlet you need to configure: RequestContextFilter
Gareth Davis
1. attr.getSession(true); >> is protected method and is not accessible in CustomAuthenticationProvider 2. this is wht i did in my web.xml:<filter> <filter-name>requestContextFilter</filter-name> <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class> </filter> <filter-mapping> <filter-name>requestContextFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>still the same error occurs.
Salvin Francis
sorry my mistake... adapted the code from my own project which uses getRequest, the answer is updated
Gareth Davis
ok, but my point 2 is still prevalent:No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Salvin Francis
Is this wrong ?<filter> <filter-name>requestContextFilter</filter-name> <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class> </filter> <filter-mapping> <filter-name>requestContextFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Salvin Francis
nope that looks about right... try stopping your code in a debugger and checking that RequestContextFilter is in the call stack
Gareth Davis
thanks mate, it worked, turns out that i had placed this after the DelegatingFilterProxy filter in web.xmlI didnt know that the order of filters did matter here.a new lesson learnt, thanks for the effort.
Salvin Francis