authentication.adoc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  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. [tabs]
  21. ======
  22. Java::
  23. +
  24. [source,java,role="primary"]
  25. ----
  26. mvc
  27. .perform(get("/").with(user("user")))
  28. ----
  29. Kotlin::
  30. +
  31. [source,kotlin,role="secondary"]
  32. ----
  33. mvc.get("/") {
  34. with(user("user"))
  35. }
  36. ----
  37. ======
  38. You can easily make customizations.
  39. 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".
  40. [tabs]
  41. ======
  42. Java::
  43. +
  44. [source,java,role="primary"]
  45. ----
  46. mvc
  47. .perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))
  48. ----
  49. Kotlin::
  50. +
  51. [source,kotlin,role="secondary"]
  52. ----
  53. mvc.get("/admin") {
  54. with(user("admin").password("pass").roles("USER","ADMIN"))
  55. }
  56. ----
  57. ======
  58. If you have a custom `UserDetails` that you would like to use, you can easily specify that as well.
  59. 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`:
  60. [tabs]
  61. ======
  62. Java::
  63. +
  64. [source,java,role="primary"]
  65. ----
  66. mvc
  67. .perform(get("/").with(user(userDetails)))
  68. ----
  69. Kotlin::
  70. +
  71. [source,kotlin,role="secondary"]
  72. ----
  73. mvc.get("/") {
  74. with(user(userDetails))
  75. }
  76. ----
  77. ======
  78. You can run as anonymous user using the following:
  79. [tabs]
  80. ======
  81. Java::
  82. +
  83. [source,java,role="primary"]
  84. ----
  85. mvc
  86. .perform(get("/").with(anonymous()))
  87. ----
  88. Kotlin::
  89. +
  90. [source,kotlin,role="secondary"]
  91. ----
  92. mvc.get("/") {
  93. with(anonymous())
  94. }
  95. ----
  96. ======
  97. This is especially useful if you are running with a default user and wish to process a few requests as an anonymous user.
  98. If you want a custom `Authentication` (which does not need to exist) you can do so using the following:
  99. [tabs]
  100. ======
  101. Java::
  102. +
  103. [source,java,role="primary"]
  104. ----
  105. mvc
  106. .perform(get("/").with(authentication(authentication)))
  107. ----
  108. Kotlin::
  109. +
  110. [source,kotlin,role="secondary"]
  111. ----
  112. mvc.get("/") {
  113. with(authentication(authentication))
  114. }
  115. ----
  116. ======
  117. You can even customize the `SecurityContext` using the following:
  118. [tabs]
  119. ======
  120. Java::
  121. +
  122. [source,java,role="primary"]
  123. ----
  124. mvc
  125. .perform(get("/").with(securityContext(securityContext)))
  126. ----
  127. Kotlin::
  128. +
  129. [source,kotlin,role="secondary"]
  130. ----
  131. mvc.get("/") {
  132. with(securityContext(securityContext))
  133. }
  134. ----
  135. ======
  136. We can also ensure to run as a specific user for every request by using ``MockMvcBuilders``'s default request.
  137. 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":
  138. [tabs]
  139. ======
  140. Java::
  141. +
  142. [source,java,role="primary"]
  143. ----
  144. mvc = MockMvcBuilders
  145. .webAppContextSetup(context)
  146. .defaultRequest(get("/").with(user("user").roles("ADMIN")))
  147. .apply(springSecurity())
  148. .build();
  149. ----
  150. Kotlin::
  151. +
  152. [source,kotlin,role="secondary"]
  153. ----
  154. mvc = MockMvcBuilders
  155. .webAppContextSetup(context)
  156. .defaultRequest<DefaultMockMvcBuilder>(get("/").with(user("user").roles("ADMIN")))
  157. .apply<DefaultMockMvcBuilder>(springSecurity())
  158. .build()
  159. ----
  160. ======
  161. If you find you are using the same user in many of your tests, it is recommended to move the user to a method.
  162. For example, you can specify the following in your own class named `CustomSecurityMockMvcRequestPostProcessors`:
  163. [tabs]
  164. ======
  165. Java::
  166. +
  167. [source,java,role="primary"]
  168. ----
  169. public static RequestPostProcessor rob() {
  170. return user("rob").roles("ADMIN");
  171. }
  172. ----
  173. Kotlin::
  174. +
  175. [source,kotlin,role="secondary"]
  176. ----
  177. fun rob(): RequestPostProcessor {
  178. return user("rob").roles("ADMIN")
  179. }
  180. ----
  181. ======
  182. Now you can perform a static import on `CustomSecurityMockMvcRequestPostProcessors` and use that within your tests:
  183. [tabs]
  184. ======
  185. Java::
  186. +
  187. [source,java,role="primary"]
  188. ----
  189. import static sample.CustomSecurityMockMvcRequestPostProcessors.*;
  190. ...
  191. mvc
  192. .perform(get("/").with(rob()))
  193. ----
  194. Kotlin::
  195. +
  196. [source,kotlin,role="secondary"]
  197. ----
  198. import sample.CustomSecurityMockMvcRequestPostProcessors.*
  199. //...
  200. mvc.get("/") {
  201. with(rob())
  202. }
  203. ----
  204. ======
  205. [[test-mockmvc-withmockuser]]
  206. == Running as a User in Spring MVC Test with Annotations
  207. 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].
  208. For example, the following will run the test with the user with username "user", password "password", and role "ROLE_USER":
  209. [tabs]
  210. ======
  211. Java::
  212. +
  213. [source,java,role="primary"]
  214. ----
  215. @Test
  216. @WithMockUser
  217. public void requestProtectedUrlWithUser() throws Exception {
  218. mvc
  219. .perform(get("/"))
  220. ...
  221. }
  222. ----
  223. Kotlin::
  224. +
  225. [source,kotlin,role="secondary"]
  226. ----
  227. @Test
  228. @WithMockUser
  229. fun requestProtectedUrlWithUser() {
  230. mvc
  231. .get("/")
  232. // ...
  233. }
  234. ----
  235. ======
  236. Alternatively, the following will run the test with the user with username "user", password "password", and role "ROLE_ADMIN":
  237. [tabs]
  238. ======
  239. Java::
  240. +
  241. [source,java,role="primary"]
  242. ----
  243. @Test
  244. @WithMockUser(roles="ADMIN")
  245. public void requestProtectedUrlWithUser() throws Exception {
  246. mvc
  247. .perform(get("/"))
  248. ...
  249. }
  250. ----
  251. Kotlin::
  252. +
  253. [source,kotlin,role="secondary"]
  254. ----
  255. @Test
  256. @WithMockUser(roles = ["ADMIN"])
  257. fun requestProtectedUrlWithUser() {
  258. mvc
  259. .get("/")
  260. // ...
  261. }
  262. ----
  263. ======