Spring Security(三十六):12. Spring MVC Test Integration

Spring Security provides comprehensive integration with Spring MVC Testhtml

Spring Security提供與Spring MVC Test的全面集成

12.1 Setting Up MockMvc and Spring Security

In order to use Spring Security with Spring MVC Test it is necessary to add the Spring Security FilterChainProxy as a Filter. It is also necessary to add Spring Security’s TestSecurityContextHolderPostProcessor to support Running as a User in Spring MVC Test with Annotations. This can be done using Spring Security’s SecurityMockMvcConfigurers.springSecurity(). For example:java

爲了將Spring Security與Spring MVC Test一塊兒使用,有必要將Spring Security FilterChainProxy添加爲Filter。還須要添加Spring Security的TestSecurityContextHolderPostProcessor以支持在帶有Annotations的Spring MVC Test中做爲用戶運行。這能夠使用Spring Security的SecurityMockMvcConfigurers.springSecurity()來完成。例如:
 

Spring Security’s testing support requires spring-test-4.1.3.RELEASE or greater.web

import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class CsrfShowcaseTests {

	@Autowired
	private WebApplicationContext context;

	private MockMvc mvc;

	@Before
	public void setup() {
		mvc = MockMvcBuilders
				.webAppContextSetup(context)
				.apply(springSecurity()) 1
				.build();
	}

...

1.SecurityMockMvcConfigurers.springSecurity() will perform all of the initial setup we need to integrate Spring Security with Spring MVC Testspring

SecurityMockMvcConfigurers.springSecurity()將執行咱們將Spring Security與Spring MVC Test集成所需的全部初始設置

12.2 SecurityMockMvcRequestPostProcessors

Spring MVC Test provides a convenient interface called a RequestPostProcessor that can be used to modify a request. Spring Security provides a number of RequestPostProcessor implementations that make testing easier. In order to use Spring Security’s RequestPostProcessor implementations ensure the following static import is used:spring-mvc

Spring MVC Test提供了一個稱爲RequestPostProcessor的方便接口,可用於修改請求。 Spring Security提供了許多RequestPostProcessor實現,使測試更容易。爲了使用Spring Security的RequestPostProcessor實現,請確保使用如下靜態導入:
 
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;

12.2.1 Testing with CSRF Protection

When testing any non-safe HTTP methods and using Spring Security’s CSRF protection, you must be sure to include a valid CSRF Token in the request. To specify a valid CSRF token as a request parameter using the following:安全

在測試任何非安全HTTP方法並使用Spring Security的CSRF保護時,您必須確保在請求中包含有效的CSRF令牌。要使用如下命令將有效的CSRF令牌指定爲請求參數:
mvc.perform(post("/").with(csrf()))

If you like you can include CSRF token in the header instead:mvc

若是您願意,能夠在標題中包含CSRF令牌:
mvc.perform(post("/").with(csrf().asHeader()))

You can also test providing an invalid CSRF token using the following:app

mvc.perform(post("/").with(csrf().useInvalidToken()))

12.2.2 Running a Test as a User in Spring MVC Test

It is often desirable to run tests as a specific user. There are two simple ways of populating the user:ide

一般但願將測試做爲特定用戶運行。填充用戶有兩種簡單的方法:

12.2.3 Running as a User in Spring MVC Test with RequestPostProcessor

There are a number of options available to associate a user to the current HttpServletRequest. For example, the following will run as a user (which does not need to exist) with the username "user", the password "password", and the role "ROLE_USER":post

有許多選項可用於將用戶與當前的HttpServletRequest相關聯。例如,如下將以用戶(不須要存在)的形式運行,用戶名爲「user」,密碼爲「password」,角色爲「ROLE_USER」:
 

The support works by associating the user to the HttpServletRequest. To associate the request to the SecurityContextHolder you need to ensure that the SecurityContextPersistenceFilter is associated with the MockMvc instance. A few ways to do this are:

支持經過將用戶與HttpServletRequest相關聯來工做。要將請求與SecurityContextHolder相關聯,您須要確保SecurityContextPersistenceFilter與MockMvc實例相關聯。一些方法是:
  • Invoking apply(springSecurity())
  • Adding Spring Security’s FilterChainProxy to MockMvc
  • Manually adding SecurityContextPersistenceFilter to the MockMvc instance may make sense when using MockMvcBuilders.standaloneSetup
  • 使用MockMvcBuilders.standaloneSetup時,手動將SecurityContextPersistenceFilter添加到MockMvc實例可能有意義
mvc.perform(get("/").with(user("user")))

You can easily make customizations. For example, the following will run as a user (which does not need to exist) with the username "admin", the password "pass", and the roles "ROLE_USER" and "ROLE_ADMIN".

您能夠輕鬆進行自定義。例如,如下將以用戶名(admin,不須要存在)運行,用戶名爲「admin」,密碼爲「pass」,角色爲「ROLE_USER」和「ROLE_ADMIN」。
mvc.perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))

If you have a custom UserDetails that you would like to use, you can easily specify that as well. For example, the following will use the specified UserDetails (which does not need to exist) to run with a UsernamePasswordAuthenticationToken that has a principal of the specified UserDetails:

若是您有本身想要使用的自定義UserDetails,您也能夠輕鬆指定它。例如,如下將使用指定的UserDetails(不須要存在)來運行具備指定UserDetails的主體的UsernamePasswordAuthenticationToken:
 
You can run as anonymous user using the following:
您能夠使用如下方式以匿名用戶身份運行:
mvc.perform(get("/").with(anonymous()))

This is especially useful if you are running with a default user and wish to execute a few requests as an anonymous user.

若是您使用默認用戶運行並但願以匿名用戶身份執行一些請求,則此功能尤爲有用。
 
If you want a custom  Authentication (which does not need to exist) you can do so using the following:
若是須要自定義身份驗證(不須要存在),能夠使用如下命令執行此操做:
mvc.perform(get("/").with(authentication(authentication)))

You can even customize the SecurityContext using the following:

您甚至能夠使用如下方法自定義SecurityContext:
mvc.perform(get("/").with(securityContext(securityContext)))

We can also ensure to run as a specific user for every request by using MockMvcBuilders's default request. For example, the following will run as a user (which does not need to exist) with the username "admin", the password "password", and the role "ROLE_ADMIN":

咱們還能夠經過使用MockMvcBuilders的默認請求確保以每一個請求的特定用戶身份運行。例如,如下將以用戶名(admin,不須要存在)運行,用戶名爲「admin」,密碼爲「password」,角色爲「ROLE_ADMIN」:
mvc = MockMvcBuilders
		.webAppContextSetup(context)
		.defaultRequest(get("/").with(user("user").roles("ADMIN")))
		.apply(springSecurity())
		.build();

If you find you are using the same user in many of your tests, it is recommended to move the user to a method. For example, you can specify the following in your own class named CustomSecurityMockMvcRequestPostProcessors:

若是您發如今許多測試中使用的是同一個用戶,建議將用戶移動到某個方法。例如,您能夠在本身的名爲CustomSecurityMockMvcRequestPostProcessors的類中指定如下內容:
public static RequestPostProcessor rob() {
	return user("rob").roles("ADMIN");
}

Now you can perform a static import on SecurityMockMvcRequestPostProcessors and use that within your tests:

如今,您能夠在SecurityMockMvcRequestPostProcessors上執行靜態導入,並在測試中使用它:
 
import static sample.CustomSecurityMockMvcRequestPostProcessors.*;

...

mvc
	.perform(get("/").with(rob()))

Running as a User in Spring MVC Test with Annotations

在帶有註釋的Spring MVC測試中做爲用戶運行
 
As an alternative to using a  RequestPostProcessor to create your user, you can use annotations described in  Chapter 11, Testing Method Security. For example, the following will run the test with the user with username "user", password "password", and role "ROLE_USER":
做爲使用RequestPostProcessor建立用戶的替代方法,您能夠使用第11章測試方法安全性中描述的註釋。例如,如下將使用用戶名「user」,密碼「password」和角色「ROLE_USER」運行測試:
@Test
@WithMockUser
public void requestProtectedUrlWithUser() throws Exception {
mvc
		.perform(get("/"))
		...
}

Alternatively, the following will run the test with the user with username "user", password "password", and role "ROLE_ADMIN":

或者,如下將使用用戶名「user」,密碼「password」和角色「ROLE_ADMIN」運行測試:
@Test
@WithMockUser(roles="ADMIN")
public void requestProtectedUrlWithUser() throws Exception {
mvc
		.perform(get("/"))
		...
}

12.2.4 Testing HTTP Basic Authentication

While it has always been possible to authenticate with HTTP Basic, it was a bit tedious to remember the header name, format, and encode the values. Now this can be done using Spring Security’s httpBasic RequestPostProcessor. For example, the snippet below:

雖然始終能夠使用HTTP Basic進行身份驗證,但記住標題名稱,格式和編碼值有點乏味。如今能夠使用Spring Security的httpBasic RequestPostProcessor來完成。例如,下面的代碼段:
mvc.perform(get("/").with(httpBasic("user","password")))

will attempt to use HTTP Basic to authenticate a user with the username "user" and the password "password" by ensuring the following header is populated on the HTTP Request:

將經過確保在HTTP請求上填充如下標頭,嘗試使用HTTP Basic使用用戶名「user」和密碼「password」對用戶進行身份驗證:
Authorization: Basic dXNlcjpwYXNzd29yZA==

12.3 SecurityMockMvcRequestBuilders

Spring MVC Test also provides a RequestBuilder interface that can be used to create the MockHttpServletRequest used in your test. Spring Security provides a few RequestBuilder implementations that can be used to make testing easier. In order to use Spring Security’s RequestBuilder implementations ensure the following static import is used:

Spring MVC Test還提供了一個RequestBuilder接口,可用於建立測試中使用的MockHttpServletRequest。 Spring Security提供了一些RequestBuilder實現,可用於簡化測試。爲了使用Spring Security的RequestBuilder實現,請確保使用如下靜態導入:
 
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*;

  

12.3.1 Testing Form Based Authentication

You can easily create a request to test a form based authentication using Spring Security’s testing support. For example, the following will submit a POST to "/login" with the username "user", the password "password", and a valid CSRF token:

mvc.perform(formLogin())

It is easy to customize the request. For example, the following will submit a POST to "/auth" with the username "admin", the password "pass", and a valid CSRF token:

能夠輕鬆自定義請求。例如,如下內容將使用用戶名「admin」,密碼「pass」和有效的CSRF令牌向「/ auth」提交POST:
mvc.perform(formLogin("/auth").user("admin").password("pass"))

We can also customize the parameters names that the username and password are included on. For example, this is the above request modified to include the username on the HTTP parameter "u" and the password on the HTTP parameter "p".

咱們還能夠自定義包含用戶名和密碼的參數名稱。例如,這是上面的請求被修改成包括HTTP參數「u」上的用戶名和HTTP參數「p」上的密碼。
mvc.perform(formLogin("/auth").user("u","admin").password("p","pass"))

12.3.2 Testing Logout

While fairly trivial using standard Spring MVC Test, you can use Spring Security’s testing support to make testing log out easier. For example, the following will submit a POST to "/logout" with a valid CSRF token:

雖然使用標準的Spring MVC測試至關簡單,但您能夠使用Spring Security的測試支持來簡化測試註銷。例如,如下內容將使用有效的CSRF令牌向「/ logout」提交POST:
 
mvc.perform(logout())

You can also customize the URL to post to. For example, the snippet below will submit a POST to "/signout" with a valid CSRF token:

您還能夠自定義要發佈到的URL。例如,下面的代碼段將使用有效的CSRF令牌向「/ signout」提交POST:
mvc.perform(logout("/signout"))

12.4 SecurityMockMvcResultMatchers

At times it is desirable to make various security related assertions about a request. To accommodate this need, Spring Security Test support implements Spring MVC Test’s ResultMatcher interface. In order to use Spring Security’s ResultMatcher implementations ensure the following static import is used:

有時但願對請求作出各類與安全相關的斷言。爲了知足這種需求,Spring Security Test支持實現了Spring MVC Test的ResultMatcher接口。爲了使用Spring Security的ResultMatcher實現,請確保使用如下靜態導入:
mvc
	.perform(formLogin().password("invalid"))
	.andExpect(unauthenticated());

12.4.2 Authenticated Assertion

It is often times that we must assert that an authenticated user exists. For example, we may want to verify that we authenticated successfully. We could verify that a form based login was successful with the following snippet of code:

一般咱們必須斷言通過身份驗證的用戶存在。例如,咱們可能想驗證咱們是否已成功驗證。咱們能夠使用如下代碼片斷驗證基於表單的登陸是否成功:
mvc
	.perform(formLogin())
	.andExpect(authenticated());

If we wanted to assert the roles of the user, we could refine our previous code as shown below:

若是咱們想要斷言用戶的角色,咱們能夠優化咱們以前的代碼,以下所示:
mvc
	.perform(formLogin().user("admin"))
	.andExpect(authenticated().withRoles("USER","ADMIN"));

Alternatively, we could verify the username:

或者,咱們能夠驗證用戶名:
mvc
	.perform(formLogin().user("admin"))
	.andExpect(authenticated().withUsername("admin"));

We can also combine the assertions:

mvc
	.perform(formLogin().user("admin").roles("USER","ADMIN"))
	.andExpect(authenticated().withUsername("admin"));
相關文章
相關標籤/搜索