使用 Spring Security 进行单元测试 [英] Unit testing with Spring Security

查看:74
本文介绍了使用 Spring Security 进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的公司一直在评估 Spring MVC 以确定我们是否应该在我们的下一个项目中使用它.到目前为止,我喜欢我所看到的,现在我正在查看 Spring Security 模块,以确定它是否是我们可以/应该使用的东西.

My company has been evaluating Spring MVC to determine if we should use it in one of our next projects. So far I love what I've seen, and right now I'm taking a look at the Spring Security module to determine if it's something we can/should use.

我们的安全要求非常基本;用户只需提供用户名和密码即可访问网站的某些部分(例如获取有关其帐户的信息);并且网站上有一些页面(常见问题解答、支持等)应授予匿名用户访问权限.

Our security requirements are pretty basic; a user just needs to be able to provide a username and password to be able to access certain parts of the site (such as to get info about their account); and there are a handful of pages on the site (FAQs, Support, etc) where an anonymous user should be given access.

在我创建的原型中,我一直在 Session 中为经过身份验证的用户存储一个LoginCredentials"对象(它只包含用户名和密码);例如,一些控制器检查此对象是否在会话中以获取对登录用户名的引用.我正在寻求用 Spring Security 替换这种自有逻辑,这将有一个很好的好处,即删除任何类型的我们如何跟踪登录用户?"以及我们如何对用户进行身份验证?"从我的控制器/业务代码.

In the prototype I've been creating, I have been storing a "LoginCredentials" object (which just contains username and password) in Session for an authenticated user; some of the controllers check to see if this object is in session to get a reference to the logged-in username, for example. I'm looking to replace this home-grown logic with Spring Security instead, which would have the nice benefit of removing any sort of "how do we track logged in users?" and "how do we authenticate users?" from my controller/business code.

似乎 Spring Security 提供了一个(每线程)上下文"对象,以便能够从应用程序的任何位置访问用户名/主体信息...

It seems like Spring Security provides a (per-thread) "context" object to be able to access the username/principal info from anywhere in your app...

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

...这看起来非常不像 Spring,因为这个对象在某种程度上是一个(全局)单例.

... which seems very un-Spring like as this object is a (global) singleton, in a way.

我的问题是:如果这是在 Spring Security 中访问有关经过身份验证的用户的信息的标准方法,那么将 Authentication 对象注入到 SecurityContext 中的可接受方法是什么,以便在单元测试时它可用于我的单元测试测试需要经过身份验证的用户?

My question is this: if this is the standard way to access information about the authenticated user in Spring Security, what is the accepted way to inject an Authentication object into the SecurityContext so that it is available for my unit tests when the unit tests require an authenticated user?

我需要在每个测试用例的初始化方法中连接它吗?

Do I need to wire this up in the initialization method of each test case?

protected void setUp() throws Exception {
    ...
    SecurityContextHolder.getContext().setAuthentication(
        new UsernamePasswordAuthenticationToken(testUser.getLogin(), testUser.getPassword()));
    ...
}

这似乎过于冗长.有更容易的方法吗?

This seems overly verbose. Is there an easier way?

SecurityContextHolder 对象本身看起来非常不像 Spring...

The SecurityContextHolder object itself seems very un-Spring-like...

推荐答案

问题在于 Spring Security 没有将 Authentication 对象作为容器中的 bean 提供,因此无法轻松地将其注入或自动装配出盒子.

The problem is that Spring Security does not make the Authentication object available as a bean in the container, so there is no way to easily inject or autowire it out of the box.

在我们开始使用 Spring Security 之前,我们会在容器中创建一个会话范围的 bean 来存储 Principal,将其注入AuthenticationService"(单例),然后将此 bean 注入其他需要了解 Principal 的服务中现任校长.

Before we started to use Spring Security, we would create a session-scoped bean in the container to store the Principal, inject this into an "AuthenticationService" (singleton) and then inject this bean into other services that needed knowledge of the current Principal.

如果您正在实现自己的身份验证服务,您基本上可以做同样的事情:创建一个具有主体"属性的会话范围的 bean,将其注入您的身份验证服务,让身份验证服务设置成功身份验证的属性,然后根据需要将身份验证服务提供给其他 bean.

If you are implementing your own authentication service, you could basically do the same thing: create a session-scoped bean with a "principal" property, inject this into your authentication service, have the auth service set the property on successful auth, and then make the auth service available to other beans as you need it.

我不会对使用 SecurityContextHolder 感到太糟糕.尽管.我知道它是一个静态/单例,并且 Spring 不鼓励使用这些东西,但它们的实现会根据环境注意适当的行为:Servlet 容器中的会话范围,JUnit 测试中的线程范围等.真正的限制因素单例的特点是它提供了一种对不同环境不灵活的实现.

I wouldn't feel too bad about using SecurityContextHolder. though. I know that it's a static / Singleton and that Spring discourages using such things but their implementation takes care to behave appropriately depending on the environment: session-scoped in a Servlet container, thread-scoped in a JUnit test, etc. The real limiting factor of a Singleton is when it provides an implementation that is inflexible to different environments.

这篇关于使用 Spring Security 进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆