Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring 3, Spring Security. Extract authenticated User object

This is a Spring Security question.

In my application, I have a User entity as a domain object. This object contains implementation to support Spring UserDetails object. The authentication (login/logout) process works fine.

The challenge is that I need to extract that object from the session to make 'business logic' decisions in my code.

I've been reading about querying SecurityContextHolder, but frankly, I still don't know what is the best approach, given that multiple Spring versions seem to be a factor in those discussions. Also, the Principal object isn't a solution for me, as it does not seem to contain any access level or role information.

Below is a simple controller to illustrate my challenge. It has my User domain object hardcoded. I need to replace that block with code that will obtain the User object from Spring Security session. I'm looking for the best way to do this within Spring 3.

  1. Can I get this object as my domain object or do I need to get it as Spring UserDetails object and manually convert it?
  2. Can this Security context lookup be injected somehow into my controller?

    public class HomeController {
        @RequestMapping(value="/home.html", method=RequestMethod.GET)
        public ModelAndView getHomePage(Map<String, Object> model) {
    
            // Get current user
            User currentUser=new User();
            currentUser.setUserName("Admin");
            currentUser.setAccessLevel(UserAccessLevel.ADMINISTRATOR);
    
            // Construct HomePage bean  
            HomeBean bean=new HomeBean();
            bean.setCurrentUserName(currentUser.getUserName());
    
            // Construct list of catalogs
            Collection<String> catalogList=new ArrayList<String>();
            catalogList.add("articles");
            catalogList.add("files");
            catalogList.add("comments");
            if(currentUser.hasAdministratorAccessLevel()) {
                catalogList.add("users");
            }
            bean.setCatalogList(catalogList);
    
            // Construct and return ModelAndView
            ModelAndView mav=new ModelAndView();
            mav.setViewName(WebView.HOME_PAGE.getViewName());
            mav.addObject(bean.getBeanId(), bean);
    
            return mav;
        }
    

=== Update 2012-01-07 ======================================================

I'm working with Luke's suggestion. The method that gets UserDetails from session and converts it to a returned my domain User object is in my UserService.

Here's my controller:

@Controller
public class HomeController {
@Autowired
private UserService userService;

@RequestMapping(value="/home.html", method=RequestMethod.GET)
public ModelAndView getHomePage(Map<String, Object> model) {

    // Construct HomePage bean  
    HomeBean bean=new HomeBean();
    User currentUser=userService.getCurrentlyAuthenticatedUser();
    bean.setCurrentUserName(currentUser.getUserName());

And here's key code from UserServiceImpl.getCurrentlyAuthenticatedUser():

@Override
public User getCurrentlyAuthenticatedUser() {
    User currentUser=new User();

    Authentication a = SecurityContextHolder.getContext().getAuthentication();
    UserDetails currentUserDetails = (UserDetails) a.getPrincipal();
    if(currentUserDetails==null) {
        return currentUser;
    }

    currentUser.setUserName(currentUserDetails.getUsername());

This works but am I doing this right? Feedback much appreciated. I am still unable to retrieve my User domain object from the session. I'm retrieving Spring's UserDetails object and with it constructing my domain User object but in the process some information is lost.

like image 966
jacekn Avatar asked Feb 22 '23 22:02

jacekn


1 Answers

Normally, the principal object contained in the successful Authentication will be an instance of your user object. So, for a quick solution, use

Authentication a = SecurityContextHolder.getContext().getAuthentication();
User currentUser = (User)a.getPrincipal();

But also (once you get that working), you might want to look at the answer I just gave (to a similar question) on how to inject a custom security context accessor.

like image 150
Shaun the Sheep Avatar answered May 11 '23 22:05

Shaun the Sheep