Spring 具有自定义过滤器和多个身份验证提供程序的 REST 安全性 - 成功身份验证时未调用目标方法
Spring REST Security with Custom Filters and Multiple Authentication Providers - Target Method Not Called On Successful Authentication
我正在为 REST 服务实施 Spring 安全模块。它涉及 2 个自定义过滤器和 2 个自定义身份验证提供程序。该应用程序使用 Spring 4.1.5.RELEASE 和 Spring 安全 4.0.0.RELEASE。没有XML。
身份验证成功后,我的自定义 AuthenticationSuccessHandler
就可以正常调用了。在 onAuthenticationSuccess
方法内部,我只是简单地重构了原来的 URL 并转发了请求。但是请求永远不会到达 REST 服务。我没有收到任何错误,只有一个状态为 200 的空响应。我通过删除自定义过滤器进行了检查,服务正常调用。即使在调用成功处理程序之后我也无法弄清楚。为什么请求从未到达目标?请帮忙
WebSecurityConfigurerAdapter
实施:
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(usernamePasswordAuthProvider)
.authenticationProvider(tokenAuthProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(serviceRegistrationValidatingFilter,
CustomUsernamePasswordAuthenticationFilter.class)
.addFilter(authFilter);
}
AuthenticationEntryPoint
实施:
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
authException.getMessage());
}
}
AuthenticationSuccessHandler
实施:
@Component
public class RestAuthenticationSuccessHandler extends
SimpleUrlAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
String path = Joiner.on("/")
.join(request.getServletPath(), request.getPathInfo())
.replaceAll("//", "/");
request.getRequestDispatcher(path).forward(request, response);
clearAuthenticationAttributes(request);
}
}
显示创建的过滤器链的日志(为简洁起见,省略了包名称和哈希码)。我的过滤器在我希望的位置。
INFO: Creating filter chain: AnyRequestMatcher, [WebAsyncManagerIntegrationFilter, SecurityContextPersistenceFilter, HeaderWriterFilter, CsrfFilter, LogoutFilter, ServiceRegistrationValidatingFilter, CustomUsernamePasswordAuthenticationFilter, RequestCacheAwareFilter, SecurityContextHolderAwareRequestFilter, AnonymousAuthenticationFilter, SessionManagementFilter, ExceptionTranslationFilter, FilterSecurityInterceptor]
所以问题原来是使用 Spring MockMvc。我需要使用 forwardedUrl("forwardToUrl")
进行验证。正如我在上面发布的那样,实际的转发并没有发生。 content().string("expectedString")
也没有用,内容是空白的。
看来 MockMvc
旨在测试行为,而不是数据。
mockMvc.perform(get("/form"))
.andExpect(status().isOk())
.andExpect(content().string("expectedString"))
.andExpect(forwardedUrl("forwardToUrl"));
我正在为 REST 服务实施 Spring 安全模块。它涉及 2 个自定义过滤器和 2 个自定义身份验证提供程序。该应用程序使用 Spring 4.1.5.RELEASE 和 Spring 安全 4.0.0.RELEASE。没有XML。
身份验证成功后,我的自定义 AuthenticationSuccessHandler
就可以正常调用了。在 onAuthenticationSuccess
方法内部,我只是简单地重构了原来的 URL 并转发了请求。但是请求永远不会到达 REST 服务。我没有收到任何错误,只有一个状态为 200 的空响应。我通过删除自定义过滤器进行了检查,服务正常调用。即使在调用成功处理程序之后我也无法弄清楚。为什么请求从未到达目标?请帮忙
WebSecurityConfigurerAdapter
实施:
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(usernamePasswordAuthProvider)
.authenticationProvider(tokenAuthProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(serviceRegistrationValidatingFilter,
CustomUsernamePasswordAuthenticationFilter.class)
.addFilter(authFilter);
}
AuthenticationEntryPoint
实施:
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
authException.getMessage());
}
}
AuthenticationSuccessHandler
实施:
@Component
public class RestAuthenticationSuccessHandler extends
SimpleUrlAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
String path = Joiner.on("/")
.join(request.getServletPath(), request.getPathInfo())
.replaceAll("//", "/");
request.getRequestDispatcher(path).forward(request, response);
clearAuthenticationAttributes(request);
}
}
显示创建的过滤器链的日志(为简洁起见,省略了包名称和哈希码)。我的过滤器在我希望的位置。
INFO: Creating filter chain: AnyRequestMatcher, [WebAsyncManagerIntegrationFilter, SecurityContextPersistenceFilter, HeaderWriterFilter, CsrfFilter, LogoutFilter, ServiceRegistrationValidatingFilter, CustomUsernamePasswordAuthenticationFilter, RequestCacheAwareFilter, SecurityContextHolderAwareRequestFilter, AnonymousAuthenticationFilter, SessionManagementFilter, ExceptionTranslationFilter, FilterSecurityInterceptor]
所以问题原来是使用 Spring MockMvc。我需要使用 forwardedUrl("forwardToUrl")
进行验证。正如我在上面发布的那样,实际的转发并没有发生。 content().string("expectedString")
也没有用,内容是空白的。
看来 MockMvc
旨在测试行为,而不是数据。
mockMvc.perform(get("/form"))
.andExpect(status().isOk())
.andExpect(content().string("expectedString"))
.andExpect(forwardedUrl("forwardToUrl"));