- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在我的应用程序中实现 JWT 身份验证。一切正常,但是当我运行已经存在的 @WebMvcTests 并检查返回的状态代码时,它们都失败并显示“实际:403”。
这是我当前的测试套件之一:
@WebMvcTest(controllers = UserController.class)
@ContextConfiguration(classes = {JwtServiceImpl.class}) // custom filter dependency
class UserControllerTest {
/**
* Mocked bean because it's a dependency of the SecurityConfiguration
*/
@MockBean
private UserDetailsService userDetailsService;
@MockBean
private UserService userService;
@Autowired
private ObjectMapper jsonMapper;
@Autowired
private MockMvc mockMvc;
@Test
void create_should_return_registered_user_when_request_is_valid() throws Exception {
// given
final String EMAIL = "test@test.com";
final String PASSWORD = "test_password";
final UserDto userDto = buildDto(EMAIL, PASSWORD);
final User expectedUser = buildUser(EMAIL, PASSWORD);
// when
when(userService.registerUser(userDto)).thenReturn(expectedUser);
// then
MvcResult response = mockMvc.perform(post(UserAPI.BASE_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonMapper.writeValueAsString(userDto)))
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
String responseBodyJson = response.getResponse().getContentAsString();
User responseUser = jsonMapper.readValue(responseBodyJson, User.class);
assertThat(responseUser.getId(), is(equalTo(expectedUser.getId())));
assertThat(responseUser.getEmail(), is(equalTo(expectedUser.getEmail())));
assertThat(responseUser.getPassword(), is(nullValue()));
verify(userService, times(1)).registerUser(userDto);
verifyNoMoreInteractions(userService);
}
...
}
这是我的自定义过滤器:
@Slf4j
@Component
@RequiredArgsConstructor
public class AuthorizationFilter extends OncePerRequestFilter {
public static final String AUTHORIZATION_HEADER_KEY = "Authorization";
public static final String AUTHORIZATION_HEADER_PREFIX = "Bearer ";
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String header = request.getHeader(AUTHORIZATION_HEADER_KEY);
if (hasText(header) && header.startsWith(AUTHORIZATION_HEADER_PREFIX)) {
String jwt = header.substring(AUTHORIZATION_HEADER_PREFIX.length());
Authentication establishedPrincipal = SecurityContextHolder.getContext().getAuthentication();
if (!jwtService.isTokenExpired(jwt) && establishedPrincipal == null) {
try {
String username = jwtService.extractUsername(jwt);
try {
UserDetails principal = userDetailsService.loadUserByUsername(username);
setRequestSession(request, principal);
} catch (UsernameNotFoundException exception) {
log.warn("Could not find user: {} extracted from jwt: {}", username, jwt);
}
} catch (ExpiredJwtException exception) {
log.warn("Request to parse expired JWT: {} failed: {}", jwt, exception.getMessage());
} catch (UnsupportedJwtException exception) {
log.warn("Request to parse unsupported JWT: {} failed: {}", jwt, exception.getMessage());
} catch (MalformedJwtException exception) {
log.warn("Request to parse invalid JWT: {} failed: {}", jwt, exception.getMessage());
} catch (SignatureException exception) {
log.warn("Request to parse JWT with invalid signature: {} failed: {}", jwt, exception.getMessage());
} catch (IllegalArgumentException exception) {
log.warn("Request to parse empty or null JWT: {} failed: {}", jwt, exception.getMessage());
}
}
}
filterChain.doFilter(request, response);
}
private void setRequestSession(HttpServletRequest request, UserDetails principal) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(principal,
null, principal.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
显然 MockMvc 会自动选择过滤器。如果我从过滤器中删除 @Component,Spring Context 将不再拾取它,并且测试全部通过!
所以问题显然是过滤器,但我已经在 doFilter 的第一行设置了断点,但没有命中...
也许我应该自己配置 MockMvc 而不是 Autowiring 它?但如何呢?
这是测试运行的完整输出:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/v1/users
Parameters = {}
Headers = [Content-Type:"application/json", Content-Length:"52"]
Body = <no character encoding set>
Session Attrs = {org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken@62735b13}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 403
Error message = Forbidden
Headers = [X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<400> but was:<403>
Expected :400
Actual :403
<Click to see difference>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:122)
at org.springframework.test.web.servlet.result.StatusResultMatchers.lambda$matcher$9(StatusResultMatchers.java:627)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:196)
at com.example.ordersapi.user.controller.UserControllerTest.create_should_return_bad_request_when_request_has_invalid_email(UserControllerTest.java:111)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
...
如果我设置 logging.level.org.springframework.security=DEBUG
我还可以在日志中看到一些有趣的内容:
:: Spring Boot :: (v2.2.2.RELEASE)
2020-01-16 18:57:04.484 INFO 30809 --- [ main] c.e.o.u.controller.UserControllerTest : Starting UserControllerTest on Joaos-MBP.lan with PID 30809 (started by joao in /Users/joao/Projects/orders-api-spring-web-mvc)
2020-01-16 18:57:04.486 DEBUG 30809 --- [ main] c.e.o.u.controller.UserControllerTest : Running with Spring Boot v2.2.2.RELEASE, Spring v5.2.2.RELEASE
2020-01-16 18:57:04.499 INFO 30809 --- [ main] c.e.o.u.controller.UserControllerTest : No active profile set, falling back to default profiles: default
2020-01-16 18:57:06.389 INFO 30809 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-01-16 18:57:06.736 DEBUG 30809 --- [ main] eGlobalAuthenticationAutowiredConfigurer : Eagerly initializing {org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration=org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration@1d289d3f}
2020-01-16 18:57:06.806 DEBUG 30809 --- [ main] s.s.c.a.w.c.WebSecurityConfigurerAdapter : Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).
2020-01-16 18:57:06.898 DEBUG 30809 --- [ main] edFilterInvocationSecurityMetadataSource : Adding web access control expression 'authenticated', for any request
2020-01-16 18:57:06.909 DEBUG 30809 --- [ main] o.s.s.w.a.i.FilterSecurityInterceptor : Validated configuration attributes
2020-01-16 18:57:06.912 DEBUG 30809 --- [ main] o.s.s.w.a.i.FilterSecurityInterceptor : Validated configuration attributes
2020-01-16 18:57:06.932 INFO 30809 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@7911cc15, org.springframework.security.web.context.SecurityContextPersistenceFilter@5e3db14, org.springframework.security.web.header.HeaderWriterFilter@2aea717c, org.springframework.security.web.csrf.CsrfFilter@57cabdc3, org.springframework.security.web.authentication.logout.LogoutFilter@78d92eef, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@27ab206, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@7b9e25bd, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@4409cae6, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@34f7b44f, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@1ee40b5c, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@4a22e4d7, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@14e750c5, org.springframework.security.web.session.SessionManagementFilter@7d133fb7, org.springframework.security.web.access.ExceptionTranslationFilter@37d3e140, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@3de79067]
2020-01-16 18:57:07.011 INFO 30809 --- [ main] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring TestDispatcherServlet ''
2020-01-16 18:57:07.011 INFO 30809 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
2020-01-16 18:57:07.022 INFO 30809 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 10 ms
2020-01-16 18:57:07.071 INFO 30809 --- [ main] c.e.o.u.controller.UserControllerTest : Started UserControllerTest in 3.236 seconds (JVM running for 5.213)
2020-01-16 18:57:07.192 DEBUG 30809 --- [ main] o.s.security.web.FilterChainProxy : /api/v1/users at position 1 of 15 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-01-16 18:57:07.193 DEBUG 30809 --- [ main] o.s.security.web.FilterChainProxy : /api/v1/users at position 2 of 15 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-01-16 18:57:07.194 DEBUG 30809 --- [ main] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2020-01-16 18:57:07.194 DEBUG 30809 --- [ main] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2020-01-16 18:57:07.196 DEBUG 30809 --- [ main] o.s.security.web.FilterChainProxy : /api/v1/users at position 3 of 15 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-01-16 18:57:07.197 DEBUG 30809 --- [ main] o.s.security.web.FilterChainProxy : /api/v1/users at position 4 of 15 in additional filter chain; firing Filter: 'CsrfFilter'
2020-01-16 18:57:07.199 DEBUG 30809 --- [ main] o.s.security.web.csrf.CsrfFilter : Invalid CSRF token found for http://localhost/api/v1/users
2020-01-16 18:57:07.199 DEBUG 30809 --- [ main] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@1de5cc88
2020-01-16 18:57:07.199 DEBUG 30809 --- [ main] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2020-01-16 18:57:07.201 DEBUG 30809 --- [ main] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
特别注意行 2020-01-16 18:57:07.199 DEBUG 30809 --- [ main] o.s.security.web.csrf.CsrfFilter :为 http://localhost/api 找到无效的 CSRF token /v1/用户
!我在配置中禁用了 csrf,并且它也被选中,因为我在测试中专门为其连接了一个依赖项(否则上下文初始化失败)。
安全配置如下:
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Value("${spring.h2.console.enabled:false}")
private boolean h2ConsoleEnabled;
private final UserDetailsService userDetailsService;
// private final AuthorizationFilter authorizationFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
if (h2ConsoleEnabled) {
http.authorizeRequests()
.antMatchers("/h2-console", "/h2-console/**").permitAll()
.and()
.headers().frameOptions().sameOrigin();
}
http.cors().and().csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler())
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(AuthenticationAPI.BASE_URL + "/**").permitAll()
.antMatchers(ProductAPI.BASE_URL + "/**").permitAll()
.antMatchers(UserAPI.BASE_URL + "/**").permitAll()
.anyRequest().authenticated();
// http.addFilterBefore(authorizationFilter, UsernamePasswordAuthenticationFilter.class);
}
private AuthenticationEntryPoint unauthorizedHandler() {
return (request, response, e) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
/**
* We need to override this method in order to add the @Bean annotation because Spring doesn't create an AuthenticationManager bean by default anymore.
* Without this we can't wire AuthenticationManager in other beans.
* @return AuthenticationManager bean
* @throws Exception on unsuccessful bean creation
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
我期望发生的情况:测试保持绿色,因为它们甚至不针对 protected 路由。它对于该 Controller 应该是透明的。
实际发生的情况:Spring Context 自动选取的自定义过滤器破坏了测试。如果我将其取消注册为 spring bean(删除@Component),一切都会恢复正常。
最佳答案
仅供引用,Spring 使用其默认安全配置,这就是事情变得糟糕的原因。
我不确定启用和禁用自定义过滤器到底会产生什么影响,以及为什么它会导致测试失败。不管怎样,为了解决这个问题,我必须使用 @Import 导入我自己的安全配置。然后我不得不模拟它的依赖关系。
我创建了一个辅助类,这样我就不会污染实际的 Controller 测试:
@Import(SecurityConfiguration.class)
public abstract class SecurityEnabledSetup {
/**
* Mocked bean because it's a dependency of the SecurityConfiguration
*/
@MockBean
protected UserDetailsService userDetailsService;
/**
* Mocked bean because it's a dependency of the SecurityConfiguration
*/
@MockBean
protected JwtService jwtService;
}
我的最终测试类(class)是我期望的:
@WebMvcTest(controllers = UserController.class)
class UserControllerTest extends SecurityEnabledSetup {
@MockBean
private UserService userService;
@Autowired
private ObjectMapper jsonMapper;
@Autowired
private MockMvc mockMvc;
@Test
void create_should_return_registered_user_when_request_is_valid() throws Exception {
// given
final String EMAIL = "test@test.com";
final String PASSWORD = "test_password";
final UserDto userDto = buildDto(EMAIL, PASSWORD);
final User expectedUser = buildUser(EMAIL, PASSWORD);
// when
when(userService.registerUser(userDto)).thenReturn(expectedUser);
// then
MvcResult response = mockMvc.perform(post(UserAPI.BASE_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonMapper.writeValueAsString(userDto)))
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
String responseBodyJson = response.getResponse().getContentAsString();
User responseUser = jsonMapper.readValue(responseBodyJson, User.class);
assertThat(responseUser.getId(), is(equalTo(expectedUser.getId())));
assertThat(responseUser.getEmail(), is(equalTo(expectedUser.getEmail())));
assertThat(responseUser.getPassword(), is(nullValue()));
verify(userService, times(1)).registerUser(userDto);
verifyNoMoreInteractions(userService);
}
@Test
void create_should_return_conflict_when_request_valid_but_email_in_use() throws Exception {
// given
final String EMAIL = "test@test.com";
final String PASSWORD = "test_password";
final UserDto userDto = buildDto(EMAIL, PASSWORD);
// when
when(userService.registerUser(userDto)).thenThrow(new EmailAlreadyInUseException(EMAIL));
// then
mockMvc.perform(post(UserAPI.BASE_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonMapper.writeValueAsString(userDto)))
.andExpect(status().isConflict());
verify(userService, times(1)).registerUser(userDto);
verifyNoMoreInteractions(userService);
}
@Test
void create_should_return_bad_request_when_request_has_invalid_email() throws Exception {
// given
final String BAD_EMAIL = "test_test.com";
final String PASSWORD = "test_password";
final UserDto userDto = buildDto(BAD_EMAIL, PASSWORD);
// when
// then
mockMvc.perform(post(UserAPI.BASE_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonMapper.writeValueAsString(userDto)))
.andExpect(status().isBadRequest());
verifyNoInteractions(userService);
}
@Test
void create_should_return_bad_request_when_request_has_invalid_password() throws Exception {
// given
final String EMAIL = "test@test.com";
final String BAD_PASSWORD = "";
final UserDto userDto = buildDto(EMAIL, BAD_PASSWORD);
// when
// then
mockMvc.perform(post(UserAPI.BASE_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonMapper.writeValueAsString(userDto)))
.andExpect(status().isBadRequest());
verifyNoInteractions(userService);
}
@Test
void create_should_return_bad_request_when_request_is_missing_email() throws Exception {
// given
final String PASSWORD = "test_password";
final UserDto userDto = buildDto(null, PASSWORD);
// when
// then
mockMvc.perform(post(UserAPI.BASE_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonMapper.writeValueAsString(userDto)))
.andExpect(status().isBadRequest());
verifyNoInteractions(userService);
}
@Test
void create_should_return_bad_request_when_request_is_missing_password() throws Exception {
// given
final String EMAIL = "test@test.com";
final UserDto userDto = buildDto(EMAIL, null);
// when
// then
mockMvc.perform(post(UserAPI.BASE_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonMapper.writeValueAsString(userDto)))
.andExpect(status().isBadRequest());
verifyNoInteractions(userService);
}
private UserDto buildDto(String email, String password) {
UserDto userDto = new UserDto();
userDto.setEmail(email);
userDto.setPassword(password);
return userDto;
}
private User buildUser(String email, String password){
User user = new User();
user.setId(1);
user.setEmail(email);
user.setPassword(password);
return user;
}
}
我已经在安全配置中启用了过滤器,一切都按预期工作:
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Value("${spring.h2.console.enabled:false}")
private boolean h2ConsoleEnabled;
private final UserDetailsService userDetailsService;
private final AuthorizationFilter authorizationFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
if (h2ConsoleEnabled) {
http.authorizeRequests()
.antMatchers("/h2-console", "/h2-console/**").permitAll()
.and()
.headers().frameOptions().sameOrigin();
}
http.cors().and().csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler())
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(AuthenticationAPI.BASE_URL + "/**").permitAll()
.antMatchers(ProductAPI.BASE_URL + "/**").permitAll()
.antMatchers(UserAPI.BASE_URL + "/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authorizationFilter, UsernamePasswordAuthenticationFilter.class);
}
private AuthenticationEntryPoint unauthorizedHandler() {
return (request, response, e) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
/**
* We need to override this method in order to add the @Bean annotation because Spring doesn't create an AuthenticationManager bean by default anymore.
* Without this we can't wire AuthenticationManager in other beans.
* @return AuthenticationManager bean
* @throws Exception on unsuccessful bean creation
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
关于java - 自定义过滤器突然破坏@WebMvcTest,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59776298/
无论我在做什么,我都会得到这个输出,但模拟器不会启动,新创建的模拟器也不会启动。我在 Windows 下: 警告:./android/base/files/IniFile.cpp:155:无法处理 .
我用 package.json NPM 脚本中像这样的变量: // package.json { "version": "0.12.1", "scripts": { "get-vers
几天前,Facebook 与我们网站的连接突然停止工作,代码没有任何更改??? Facebook 做了一些改变??? http://www.presbium.sk/vstup-pre-uchadzac
我习惯于 grunt build 任务成功完成,但由于我将我的项目编辑与其他开发人员同事合并,它突然失败并出现我以前从未见过的错误: grunt build Loading "imagemin.js"
我不明白这个。突然之间,我无法使用 iOS 9.0 中引入的 UIUserNotificationActionResponseTypedTextKey 标识符来访问通知中的文本输入消息。 Xcode
在我调用某个 Google 的 Youtube 库后,我的应用程序在其回调之一后突然变得完全没有响应。 无响应意味着无法点击所有 UI 组件。 在 iOS 中是否有这样的东西可以禁用整个屏幕完全不响应
bool queueIsFull(int rearPointer) { if(rearPointer==9) return 1; else return
我正在使用 PHP、Apache 和 MySQL 开发 Web 应用程序。在过去的一年中,此应用程序的响应时间一直不错。昨天,应用程序在 Firefox 上突然变得非常慢(完整的页面加载,包括 CSS
几个小时后,从控制台发出的 PHP 命令不再接受本地路径。例如在 laravel 中我总是给出命令 php artisan 但从今晚开始我收到了以下回复 Status: 404 Not Found C
我有一个 session WCF 服务,它生成一个进程并在调用 IsInitiating 操作时打开一个到该进程的命名管道。当调用 IsTerminating 操作时,服务会沿着管道发送一条消息,通知
类似的问题已经回答了好几次,我确实检查了其中的许多问题。这是不同的,请继续阅读。 我在 strings.xml 中定义了大量(大量)字符串,并带有多个格式参数。例如: %s and also %s 这
我有一个简单的消息机器人,它是根据 Messenger 平台指南设置的。在过去的几个月里,它一直运行良好,每天发送大约六条消息。我根本没有碰它,但是突然,发送消息,即调用 https://graph.
我正在使用 Unity 开发一款简单的 3D 手机游戏。我的目标是在没有垂直同步的情况下达到 30 FPS。我的游戏在所有 iOS 设备上运行良好,没有发热和节流,但有奇怪的 FPS 下降。 FPS
我们有一个自定义小部件,多年来一直运行良好,直到上周。 看来 Json 回调现在仅适用于播放列表,不适用于轨道。 播放列表 /**/jQuery31108094578850496614_1482167
-bash:/Users/winchenzo/git-completion.bash: 没有那个文件或目录 -bash:/Users/winchenzo/git-prompt.sh: 没有那个文件或目
编辑:重启解决了问题。我仍然想知道最初是什么原因造成的,因为这种情况以前发生过一次,但我不记得当时我做了什么来修复它(当时重新启动并没有解决问题)。 我 cd 到包含我要编辑的文件的文件夹,然后从命令
我刚刚注册是因为我突然遇到了一个问题,目前为止运行良好的代码我之前在这里找到了一些非常好的答案。希望你们能再次帮助我,这次甚至是投票;) $sql='SELECT projektKurz, proje
我制作了一个小程序,它在 tcp 套接字上监听和发送线路,并将接收到的信息附加到 JTextArea。我用它在 Minecraft 服务器上聊天,而无需打开游戏。 我昨晚工作得很好,但当我起床时却不工
感谢您在这里查看我的问题。 我正在使用 Glide 从 Firebase 存储中获取图像,基本上我是在使用 url 从存储中获取图像。第一天它工作正常但突然停止获取图像。我没有碰代码。我检查了很多答案
FCM 通知已到达所有 iOS 设备。但通知在大约 1 年前注册的某些设备上不起作用。 FCM token 和 APNs token 似乎没有变化。为什么没有到达通知? FCM token 是否必须过
我是一名优秀的程序员,十分优秀!