HelloWebfluxApplicationTests.java 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. *
  3. * * Copyright 2002-2017 the original author or authors.
  4. * *
  5. * * Licensed under the Apache License, Version 2.0 (the "License");
  6. * * you may not use this file except in compliance with the License.
  7. * * You may obtain a copy of the License at
  8. * *
  9. * * http://www.apache.org/licenses/LICENSE-2.0
  10. * *
  11. * * Unless required by applicable law or agreed to in writing, software
  12. * * distributed under the License is distributed on an "AS IS" BASIS,
  13. * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * * See the License for the specific language governing permissions and
  15. * * limitations under the License.
  16. *
  17. */
  18. package sample;
  19. import org.junit.Before;
  20. import org.junit.Test;
  21. import org.junit.runner.RunWith;
  22. import org.springframework.beans.factory.annotation.Autowired;
  23. import org.springframework.context.ApplicationContext;
  24. import org.springframework.http.HttpHeaders;
  25. import org.springframework.http.HttpStatus;
  26. import org.springframework.http.ResponseCookie;
  27. import org.springframework.security.web.server.header.ContentTypeOptionsHttpHeadersWriter;
  28. import org.springframework.test.context.ActiveProfiles;
  29. import org.springframework.test.context.ContextConfiguration;
  30. import org.springframework.test.context.junit4.SpringRunner;
  31. import org.springframework.test.web.reactive.server.ExchangeMutatorWebFilter;
  32. import org.springframework.test.web.reactive.server.ExchangeResult;
  33. import org.springframework.test.web.reactive.server.WebTestClient;
  34. import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
  35. import java.nio.charset.Charset;
  36. import java.util.Base64;
  37. import static org.springframework.security.test.web.reactive.server.SecurityExchangeMutators.withUser;
  38. import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
  39. /**
  40. * @author Rob Winch
  41. * @since 5.0
  42. */
  43. @RunWith(SpringRunner.class)
  44. @ContextConfiguration(classes = HelloWebfluxApplication.class)
  45. @ActiveProfiles("test")
  46. public class HelloWebfluxApplicationTests {
  47. @Autowired
  48. ApplicationContext context;
  49. WebTestClient rest;
  50. @Before
  51. public void setup() {
  52. this.rest = WebTestClient.bindToApplicationContext(context).build();
  53. }
  54. @Test
  55. public void basicRequired() throws Exception {
  56. this.rest
  57. .get()
  58. .uri("/principal")
  59. .exchange()
  60. .expectStatus().isUnauthorized();
  61. }
  62. @Test
  63. public void basicWorks() throws Exception {
  64. this.rest
  65. .mutate()
  66. .filter(robsCredentials())
  67. .build()
  68. .get()
  69. .uri("/principal")
  70. .exchange()
  71. .expectStatus().isOk()
  72. .expectBody().json("{\"username\":\"rob\"}");
  73. }
  74. @Test
  75. public void basicWhenPasswordInvalid401() throws Exception {
  76. this.rest
  77. .mutate()
  78. .filter(invalidPassword())
  79. .build()
  80. .get()
  81. .uri("/principal")
  82. .exchange()
  83. .expectStatus().isUnauthorized()
  84. .expectBody().isEmpty();
  85. }
  86. @Test
  87. public void authorizationAdmin403() throws Exception {
  88. this.rest
  89. .mutate()
  90. .filter(robsCredentials())
  91. .build()
  92. .get()
  93. .uri("/admin")
  94. .exchange()
  95. .expectStatus().isEqualTo(HttpStatus.FORBIDDEN)
  96. .expectBody().isEmpty();
  97. }
  98. @Test
  99. public void authorizationAdmin200() throws Exception {
  100. this.rest
  101. .mutate()
  102. .filter(adminCredentials())
  103. .build()
  104. .get()
  105. .uri("/admin")
  106. .exchange()
  107. .expectStatus().isOk();
  108. }
  109. @Test
  110. public void basicMissingUser401() throws Exception {
  111. this.rest
  112. .mutate()
  113. .filter(basicAuthentication("missing-user", "password"))
  114. .build()
  115. .get()
  116. .uri("/admin")
  117. .exchange()
  118. .expectStatus().isUnauthorized();
  119. }
  120. @Test
  121. public void basicInvalidPassword401() throws Exception {
  122. this.rest
  123. .mutate()
  124. .filter(invalidPassword())
  125. .build()
  126. .get()
  127. .uri("/admin")
  128. .exchange()
  129. .expectStatus().isUnauthorized();
  130. }
  131. @Test
  132. public void basicInvalidParts401() throws Exception {
  133. this.rest
  134. .get()
  135. .uri("/admin")
  136. .header("Authorization", "Basic " + base64Encode("no colon"))
  137. .exchange()
  138. .expectStatus().isUnauthorized();
  139. }
  140. @Test
  141. public void sessionWorks() throws Exception {
  142. ExchangeResult result = this.rest
  143. .mutate()
  144. .filter(robsCredentials())
  145. .build()
  146. .get()
  147. .uri("/principal")
  148. .exchange()
  149. .returnResult(String.class);
  150. ResponseCookie session = result.getResponseCookies().getFirst("SESSION");
  151. this.rest
  152. .get()
  153. .uri("/principal")
  154. .cookie(session.getName(), session.getValue())
  155. .exchange()
  156. .expectStatus().isOk();
  157. }
  158. @Test
  159. public void mockSupport() throws Exception {
  160. ExchangeMutatorWebFilter exchangeMutator = new ExchangeMutatorWebFilter();
  161. WebTestClient mockRest = WebTestClient.bindToApplicationContext(this.context).webFilter(exchangeMutator).build();
  162. mockRest
  163. .mutate()
  164. .filter(exchangeMutator.perClient(withUser()))
  165. .build()
  166. .get()
  167. .uri("/principal")
  168. .exchange()
  169. .expectStatus().isOk();
  170. mockRest
  171. .get()
  172. .uri("/principal")
  173. .exchange()
  174. .expectStatus().isUnauthorized();
  175. }
  176. @Test
  177. public void me() throws Exception {
  178. this.rest
  179. .mutate()
  180. .filter(robsCredentials())
  181. .build()
  182. .get()
  183. .uri("/me")
  184. .exchange()
  185. .expectStatus().isOk()
  186. .expectBody().json("{\"username\" : \"rob\"}");
  187. }
  188. @Test
  189. public void monoMe() throws Exception {
  190. this.rest
  191. .mutate()
  192. .filter(robsCredentials())
  193. .build()
  194. .get()
  195. .uri("/mono/me")
  196. .exchange()
  197. .expectStatus().isOk()
  198. .expectBody().json("{\"username\" : \"rob\"}");
  199. }
  200. @Test
  201. public void principal() throws Exception {
  202. this.rest
  203. .mutate()
  204. .filter(robsCredentials())
  205. .build()
  206. .get()
  207. .uri("/principal")
  208. .exchange()
  209. .expectStatus().isOk()
  210. .expectBody().json("{\"username\" : \"rob\"}");
  211. }
  212. @Test
  213. public void headers() throws Exception {
  214. this.rest
  215. .mutate()
  216. .filter(robsCredentials())
  217. .build()
  218. .get()
  219. .uri("/principal")
  220. .exchange()
  221. .expectHeader().valueEquals(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")
  222. .expectHeader().valueEquals(HttpHeaders.EXPIRES, "0")
  223. .expectHeader().valueEquals(HttpHeaders.PRAGMA, "no-cache")
  224. .expectHeader().valueEquals(ContentTypeOptionsHttpHeadersWriter.X_CONTENT_OPTIONS, ContentTypeOptionsHttpHeadersWriter.NOSNIFF);
  225. }
  226. private ExchangeFilterFunction robsCredentials() {
  227. return basicAuthentication("rob","rob");
  228. }
  229. private ExchangeFilterFunction invalidPassword() {
  230. return basicAuthentication("rob","INVALID");
  231. }
  232. private ExchangeFilterFunction adminCredentials() {
  233. return basicAuthentication("admin","admin");
  234. }
  235. private String base64Encode(String value) {
  236. return Base64.getEncoder().encodeToString(value.getBytes(Charset.defaultCharset()));
  237. }
  238. }