我正在开发一个使用Spring Security进行用户身份验证的Web应用程序。 我知道我可以通过这种方式获得登录用户:
public class SecurityUtil {
public static User getCurrentUser() {
SecurityContextHolder.getContext().getAuthentication().getPrincipal()
}
}
这样工作正常。 问题是:哪个是获取此值的最佳方式?我会举一些例子:
1.User在控制器中声明为变量:
public class FooController {
@Autowired
private FooService fooService;
private User u = SecurityUtil.getCurrentUser();
@RequestMapping(...)
public void control() {
fooService.doSomething(u);
}
}
2.User作为传递给服务的参数:
public class FooController {
@Autowired
private FooService fooService;
public void control() {
fooService.doSomething(SecurityUtil.getCurrentUser());
}
}
3.在服务中访问用户:
public class FooService {
public void doSomething() {
SecurityUtil.getCurrentUser();
//Do something
}
}
这些例子都有效吗?我可以模糊地使用其中任何一个吗?我应该注意哪些缺点?
答案 0 :(得分:2)
示例1
示例1不可用,因为默认情况下Spring bean是singleton,这意味着在创建FooController
时,User
变量未正确分配或者是null
。正如其他答案所指出的那样,它也不是线程安全的。
示例2
示例2是我推荐的方法,它在单元测试中更容易测试。但我建议使用以下示例(Spring 3),参考doc here:
@RequestMapping(method = RequestMethod.GET)
public String index(Model m, HttpSession session, Principal principal) {
// principal.getName() return username
return "XYZ";
}
示例3
实施例3是可用的,但不易测试且难以维护。
答案 1 :(得分:0)
示例1不是线程安全的。通常,您的服务bean应该是无状态的。
使用示例3,它取决于您从控制器调用FooService
的方式。如果此调用跨越应用程序边界,那么您需要确保Spring SecurityContext
传播并调用它才能工作。
在所有情况下,示例二都应该没问题,但是将当前用户传递给服务方法似乎不是正确的关注点分离。