哪个是获得Spring安全性的登录用户的最佳方法?

时间:2012-04-03 11:40:13

标签: java spring-mvc spring-security

我正在开发一个使用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
    }
}

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

2 个答案:

答案 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传播并调用它才能工作。

在所有情况下,示例二都应该没问题,但是将当前用户传递给服务方法似乎不是正确的关注点分离。