authentication.adoc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. [[test-mockmvc-securitycontextholder]]
  2. = Running a Test as a User in Spring MVC Test
  3. It is often desirable to run tests as a specific user.
  4. There are two simple ways of populating the user:
  5. * <<Running as a User in Spring MVC Test with RequestPostProcessor,Running as a User in Spring MVC Test with RequestPostProcessor>>
  6. * <<Running as a User in Spring MVC Test with Annotations,Running as a User in Spring MVC Test with Annotations>>
  7. [[test-mockmvc-securitycontextholder-rpp]]
  8. == Running as a User in Spring MVC Test with RequestPostProcessor
  9. There are a number of options available to associate a user to the current `HttpServletRequest`.
  10. 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":
  11. [NOTE]
  12. ====
  13. The support works by associating the user to the `HttpServletRequest`.
  14. To associate the request to the `SecurityContextHolder` you need to ensure that the `SecurityContextPersistenceFilter` is associated with the `MockMvc` instance.
  15. A few ways to do this are:
  16. * Invoking xref:servlet/test/mockmvc/setup.adoc#test-mockmvc-setup[`apply(springSecurity())`]
  17. * Adding Spring Security's `FilterChainProxy` to `MockMvc`
  18. * Manually adding `SecurityContextPersistenceFilter` to the `MockMvc` instance may make sense when using `MockMvcBuilders.standaloneSetup`
  19. ====
  20. ====
  21. .Java
  22. [source,java,role="primary"]
  23. ----
  24. mvc
  25. .perform(get("/").with(user("user")))
  26. ----
  27. .Kotlin
  28. [source,kotlin,role="secondary"]
  29. ----
  30. mvc.get("/") {
  31. with(user("user"))
  32. }
  33. ----
  34. ====
  35. You can easily make customizations.
  36. 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".
  37. ====
  38. .Java
  39. [source,java,role="primary"]
  40. ----
  41. mvc
  42. .perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))
  43. ----
  44. .Kotlin
  45. [source,kotlin,role="secondary"]
  46. ----
  47. mvc.get("/admin") {
  48. with(user("admin").password("pass").roles("USER","ADMIN"))
  49. }
  50. ----
  51. ====
  52. If you have a custom `UserDetails` that you would like to use, you can easily specify that as well.
  53. 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`:
  54. ====
  55. .Java
  56. [source,java,role="primary"]
  57. ----
  58. mvc
  59. .perform(get("/").with(user(userDetails)))
  60. ----
  61. .Kotlin
  62. [source,kotlin,role="secondary"]
  63. ----
  64. mvc.get("/") {
  65. with(user(userDetails))
  66. }
  67. ----
  68. ====
  69. You can run as anonymous user using the following:
  70. ====
  71. .Java
  72. [source,java,role="primary"]
  73. ----
  74. mvc
  75. .perform(get("/").with(anonymous()))
  76. ----
  77. .Kotlin
  78. [source,kotlin,role="secondary"]
  79. ----
  80. mvc.get("/") {
  81. with(anonymous())
  82. }
  83. ----
  84. ====
  85. This is especially useful if you are running with a default user and wish to process a few requests as an anonymous user.
  86. If you want a custom `Authentication` (which does not need to exist) you can do so using the following:
  87. ====
  88. .Java
  89. [source,java,role="primary"]
  90. ----
  91. mvc
  92. .perform(get("/").with(authentication(authentication)))
  93. ----
  94. .Kotlin
  95. [source,kotlin,role="secondary"]
  96. ----
  97. mvc.get("/") {
  98. with(authentication(authentication))
  99. }
  100. ----
  101. ====
  102. You can even customize the `SecurityContext` using the following:
  103. ====
  104. .Java
  105. [source,java,role="primary"]
  106. ----
  107. mvc
  108. .perform(get("/").with(securityContext(securityContext)))
  109. ----
  110. .Kotlin
  111. [source,kotlin,role="secondary"]
  112. ----
  113. mvc.get("/") {
  114. with(securityContext(securityContext))
  115. }
  116. ----
  117. ====
  118. We can also ensure to run as a specific user for every request by using ``MockMvcBuilders``'s default request.
  119. 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":
  120. ====
  121. .Java
  122. [source,java,role="primary"]
  123. ----
  124. mvc = MockMvcBuilders
  125. .webAppContextSetup(context)
  126. .defaultRequest(get("/").with(user("user").roles("ADMIN")))
  127. .apply(springSecurity())
  128. .build();
  129. ----
  130. .Kotlin
  131. [source,kotlin,role="secondary"]
  132. ----
  133. mvc = MockMvcBuilders
  134. .webAppContextSetup(context)
  135. .defaultRequest<DefaultMockMvcBuilder>(get("/").with(user("user").roles("ADMIN")))
  136. .apply<DefaultMockMvcBuilder>(springSecurity())
  137. .build()
  138. ----
  139. ====
  140. If you find you are using the same user in many of your tests, it is recommended to move the user to a method.
  141. For example, you can specify the following in your own class named `CustomSecurityMockMvcRequestPostProcessors`:
  142. ====
  143. .Java
  144. [source,java,role="primary"]
  145. ----
  146. public static RequestPostProcessor rob() {
  147. return user("rob").roles("ADMIN");
  148. }
  149. ----
  150. .Kotlin
  151. [source,kotlin,role="secondary"]
  152. ----
  153. fun rob(): RequestPostProcessor {
  154. return user("rob").roles("ADMIN")
  155. }
  156. ----
  157. ====
  158. Now you can perform a static import on `CustomSecurityMockMvcRequestPostProcessors` and use that within your tests:
  159. ====
  160. .Java
  161. [source,java,role="primary"]
  162. ----
  163. import static sample.CustomSecurityMockMvcRequestPostProcessors.*;
  164. ...
  165. mvc
  166. .perform(get("/").with(rob()))
  167. ----
  168. .Kotlin
  169. [source,kotlin,role="secondary"]
  170. ----
  171. import sample.CustomSecurityMockMvcRequestPostProcessors.*
  172. //...
  173. mvc.get("/") {
  174. with(rob())
  175. }
  176. ----
  177. ====
  178. [[test-mockmvc-withmockuser]]
  179. == Running as a User in Spring MVC Test with Annotations
  180. As an alternative to using a `RequestPostProcessor` to create your user, you can use annotations described in xref:servlet/test/method.adoc[Testing Method Security].
  181. For example, the following will run the test with the user with username "user", password "password", and role "ROLE_USER":
  182. ====
  183. .Java
  184. [source,java,role="primary"]
  185. ----
  186. @Test
  187. @WithMockUser
  188. public void requestProtectedUrlWithUser() throws Exception {
  189. mvc
  190. .perform(get("/"))
  191. ...
  192. }
  193. ----
  194. .Kotlin
  195. [source,kotlin,role="secondary"]
  196. ----
  197. @Test
  198. @WithMockUser
  199. fun requestProtectedUrlWithUser() {
  200. mvc
  201. .get("/")
  202. // ...
  203. }
  204. ----
  205. ====
  206. Alternatively, the following will run the test with the user with username "user", password "password", and role "ROLE_ADMIN":
  207. ====
  208. .Java
  209. [source,java,role="primary"]
  210. ----
  211. @Test
  212. @WithMockUser(roles="ADMIN")
  213. public void requestProtectedUrlWithUser() throws Exception {
  214. mvc
  215. .perform(get("/"))
  216. ...
  217. }
  218. ----
  219. .Kotlin
  220. [source,kotlin,role="secondary"]
  221. ----
  222. @Test
  223. @WithMockUser(roles = ["ADMIN"])
  224. fun requestProtectedUrlWithUser() {
  225. mvc
  226. .get("/")
  227. // ...
  228. }
  229. ----
  230. ====