HelloWebfluxFnApplicationITests.java 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Copyright 2002-2017 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package sample;
  17. import org.junit.Before;
  18. import org.junit.Test;
  19. import org.junit.runner.RunWith;
  20. import org.springframework.beans.factory.annotation.Value;
  21. import org.springframework.http.HttpHeaders;
  22. import org.springframework.http.HttpStatus;
  23. import org.springframework.http.ResponseCookie;
  24. import org.springframework.security.web.server.header.ContentTypeOptionsHttpHeadersWriter;
  25. import org.springframework.test.context.ContextConfiguration;
  26. import org.springframework.test.context.TestPropertySource;
  27. import org.springframework.test.context.junit4.SpringRunner;
  28. import org.springframework.test.web.reactive.server.ExchangeResult;
  29. import org.springframework.test.web.reactive.server.WebTestClient;
  30. import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
  31. import java.nio.charset.Charset;
  32. import java.time.Duration;
  33. import java.util.Base64;
  34. import static org.springframework.security.test.web.reactive.server.SecurityExchangeMutators.withUser;
  35. import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
  36. /**
  37. * @author Rob Winch
  38. * @since 5.0
  39. */
  40. @RunWith(SpringRunner.class)
  41. @ContextConfiguration(classes = HelloWebfluxFnApplication.class)
  42. @TestPropertySource(properties = "server.port=0")
  43. public class HelloWebfluxFnApplicationITests {
  44. @Value("#{@nettyContext.address().getPort()}")
  45. int port;
  46. WebTestClient rest;
  47. @Before
  48. public void setup() {
  49. this.rest = WebTestClient.bindToServer()
  50. .responseTimeout(Duration.ofDays(1))
  51. .baseUrl("http://localhost:" + this.port)
  52. .build();
  53. }
  54. @Test
  55. public void basicRequired() throws Exception {
  56. this.rest
  57. .get()
  58. .uri("/users")
  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. String session = result.getResponseHeaders().getFirst("Set-Cookie");
  151. this.rest
  152. .get()
  153. .uri("/principal")
  154. .header("Cookie", session)
  155. .exchange()
  156. .expectStatus().isOk();
  157. }
  158. @Test
  159. public void principal() throws Exception {
  160. this.rest
  161. .mutate()
  162. .filter(robsCredentials())
  163. .build()
  164. .get()
  165. .uri("/principal")
  166. .exchange()
  167. .expectStatus().isOk()
  168. .expectBody().json("{\"username\" : \"rob\"}");
  169. }
  170. @Test
  171. public void headers() throws Exception {
  172. this.rest
  173. .mutate()
  174. .filter(robsCredentials())
  175. .build()
  176. .get()
  177. .uri("/principal")
  178. .exchange()
  179. .expectHeader().valueEquals(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate")
  180. .expectHeader().valueEquals(HttpHeaders.EXPIRES, "0")
  181. .expectHeader().valueEquals(HttpHeaders.PRAGMA, "no-cache")
  182. .expectHeader().valueEquals(ContentTypeOptionsHttpHeadersWriter.X_CONTENT_OPTIONS, ContentTypeOptionsHttpHeadersWriter.NOSNIFF);
  183. }
  184. private ExchangeFilterFunction robsCredentials() {
  185. return basicAuthentication("rob","rob");
  186. }
  187. private ExchangeFilterFunction invalidPassword() {
  188. return basicAuthentication("rob","INVALID");
  189. }
  190. private ExchangeFilterFunction adminCredentials() {
  191. return basicAuthentication("admin","admin");
  192. }
  193. private String base64Encode(String value) {
  194. return Base64.getEncoder().encodeToString(value.getBytes(Charset.defaultCharset()));
  195. }
  196. }