Java 使用spring security获取已登录用户的最佳方法是什么?

Java 使用spring security获取已登录用户的最佳方法是什么?,java,spring-mvc,spring-security,Java,Spring Mvc,Spring Security,我正在开发一个web应用程序,它使用Spring Security对用户进行身份验证。 我知道我可以通过以下方式获得登录用户: public class SecurityUtil { public static User getCurrentUser() { SecurityContextHolder.getContext().getAuthentication().getPrincipal() } } 这样做很好。 问题是:访问此值的最佳方式是什么?我将举一些

我正在开发一个web应用程序,它使用Spring Security对用户进行身份验证。 我知道我可以通过以下方式获得登录用户:

public class SecurityUtil {
    public static User getCurrentUser() {
        SecurityContextHolder.getContext().getAuthentication().getPrincipal()
    }
}
这样做很好。 问题是:访问此值的最佳方式是什么?我将举一些例子:

1.在控制器中声明为变量的用户:

public class FooController {

    @Autowired
    private FooService fooService;

    private User u = SecurityUtil.getCurrentUser();

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

        fooService.doSomething(u);
    }
}
2.用户作为参数传递给服务:

public class FooController {

    @Autowired
    private FooService fooService;

    public void control() {

        fooService.doSomething(SecurityUtil.getCurrentUser());
    }
}
public class FooService {

    public void doSomething() {

        SecurityUtil.getCurrentUser();
        //Do something
    }
}
3.在服务中访问的用户:

public class FooController {

    @Autowired
    private FooService fooService;

    public void control() {

        fooService.doSomething(SecurityUtil.getCurrentUser());
    }
}
public class FooService {

    public void doSomething() {

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

这些例子都有效吗?我可以模糊地使用其中的任何一个吗?我应该注意到一些缺点?

示例1不是线程安全的。一般来说,您的服务bean应该是无状态的

对于示例3,这取决于您如何从控制器调用
FooService
。如果此调用跨越了应用程序边界,那么您需要确保Spring
SecurityContext
与调用一起传播,以使其正常工作


示例2在所有情况下都应该是好的,但是将当前用户传递到服务方法似乎并不是正确的关注点分离

示例1

示例1不可用,因为Springbean默认为singleton,这意味着当创建
FooController
时,
User
变量分配不正确或为
null
。正如其他答案所指出的,它也不是线程安全的

示例2

示例2是我推荐的方法,它在单元测试中更易于测试。但我建议使用以下示例(Spring 3),请参考文档:

示例3


示例3是可用的,但不容易测试和维护。

您使用的是哪个版本的Spring?真的吗?您的示例在Spring3中有效吗?我不知道。。。非常优雅@Fabio,是的,它在Spring3中工作,请参阅我的更新答案以及Spring文档的链接