Fabio
Fabio

Reputation: 652

Which is the best way to get the logged user with spring security?

I'm developing a web application that use Spring Security for authentication of users. I know that i can get the logged in user in this way:

public class SecurityUtil {
    public static User getCurrentUser() {
        SecurityContextHolder.getContext().getAuthentication().getPrincipal()
    }
}

And in this way works fine. The question is: which is the best way to access this value? I will make some example:

1.User declared as variable in the controller:

public class FooController {

    @Autowired
    private FooService fooService;

    private User u = SecurityUtil.getCurrentUser();

    @RequestMapping(...)
    public void control() {

        fooService.doSomething(u);
    }
}

2.User as parameter passed to the service:

public class FooController {

    @Autowired
    private FooService fooService;

    public void control() {

        fooService.doSomething(SecurityUtil.getCurrentUser());
    }
}

3.User accessed in the service:

public class FooService {

    public void doSomething() {

        SecurityUtil.getCurrentUser();
        //Do something
    }
}

Are all this examples valid? Can I use anyone of them indistinctly? There are some drawbacks of which I should be aware of?

Upvotes: 0

Views: 408

Answers (2)

Pau Kiat Wee
Pau Kiat Wee

Reputation: 9505

Example 1

Example 1 is not usable since Spring bean by default is singleton, which mean that when the FooController is created, the User variable is not assigned correctly or it is null. As other answer point out, it is also not thread safe.

Example 2

Example 2 is my recommended way to do it, it is more testable in unit test. But I would recommend use the following example (Spring 3), refer doc here:

@RequestMapping(method = RequestMethod.GET)
public String index(Model m, HttpSession session, Principal principal) {
    // principal.getName() return username
    return "XYZ";
}

Example 3

Example 3 is usable, but not easily testable and hard to maintain.

Upvotes: 2

darrengorman
darrengorman

Reputation: 13114

Example 1 is not thread-safe. In general your service beans should be stateless.

With example 3, it depends on how you are invoking the FooService from your controller. If this invocation crosses application boundaries then you need to ensure the Spring SecurityContext propagates with the invocation for it to work.

Example two should be fine in all cases but passing the current user into the service method doesn't seem like correct separation of concerns.

Upvotes: 0

Related Questions