为什么 spring 没有按要求发送 403 响应状态?
Why isn't spring sending 403 response status as requested?
在 中,我被告知 DelegatingAuthenticationEntryPoint class。
但是,我遇到了 spring 没有返回正确的 Http 响应状态的问题。
这是我重写的配置方法
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> map = new LinkedHashMap<>();
map.put(new AntPathRequestMatcher(WELCOME_PAGE), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(FOOD_SELECTION_PAGE + "/**"), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(CHECKOUT_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(VERIFY_BADGE_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(VERIFY_NAME_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(ADMIN_PAGE), new LoginUrlAuthenticationEntryPoint(LOGIN_PAGE));
map.put(new AntPathRequestMatcher(NEW_FOOD_PAGE), new LoginUrlAuthenticationEntryPoint(LOGIN_PAGE));
map.put(new AntPathRequestMatcher(EDIT_FOOD_URL + "/**"), new LoginUrlAuthenticationEntryPoint(LOGIN_PAGE));
map.put(new AntPathRequestMatcher(HIDE_FOOD_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(SHOW_FOOD_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(DELETE_FOOD_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(REFRESH_EMPS_URL), new Http403ForbiddenEntryPoint());
http.authorizeRequests()
.antMatchers(WELCOME_PAGE,
FOOD_SELECTION_PAGE + "/**",
CHECKOUT_URL,
VERIFY_BADGE_URL,
VERIFY_NAME_URL).denyAll()
.antMatchers(ADMIN_PAGE,
NEW_FOOD_PAGE,
EDIT_FOOD_URL + "/**",
HIDE_FOOD_URL,
SHOW_FOOD_URL,
DELETE_FOOD_URL,
REFRESH_EMPS_URL).hasAnyAuthority("ROLES_USER")
.anyRequest().permitAll()
.and().formLogin().loginPage(LOGIN_PAGE)
.usernameParameter("username")
.passwordParameter("pin")
.defaultSuccessUrl(ADMIN_PAGE)
.permitAll()
.failureUrl(LOGIN_PAGE + "?badlogin")
.and().exceptionHandling().authenticationEntryPoint(new DelegatingAuthenticationEntryPoint(map));
}
我正在使用 postman 执行对 VERIFY_BADGE_URL 的 post 请求。如这些日志中所示,DelegatingAuthenticationEntryPoint 正确地将此请求映射到 Http403ForbiddenEntryPoint
2021-08-18 10:18:57,879 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint: Match found! Executing org.springframework.security.web.authentication.Http403ForbiddenEntryPoint@8f8351a
2021-08-18 10:18:57,879 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.authentication.Http403ForbiddenEntryPoint: Pre-authenticated entry point called. Rejecting access
然后在进一步处理后,我注意到它最终被转换为 405 状态并返回给 postman,如这些日志中所见。
2021-08-18 10:18:57,880 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper: Did not store empty SecurityContext
2021-08-18 10:18:57,881 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper: Did not store empty SecurityContext
2021-08-18 10:18:57,881 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.SecurityContextPersistenceFilter: Cleared SecurityContextHolder to complete request
2021-08-18 10:18:57,881 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Processing ErrorPage[errorCode=0, location=/error]
2021-08-18 10:18:57,884 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.FilterChainProxy: Securing POST /error
2021-08-18 10:18:57,884 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.SecurityContextPersistenceFilter: Set SecurityContextHolder to empty SecurityContext
2021-08-18 10:18:57,884 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.authentication.AnonymousAuthenticationFilter: Set SecurityContextHolder to anonymous SecurityContext
2021-08-18 10:18:57,884 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.FilterChainProxy$VirtualFilterChain: Secured POST /error
2021-08-18 10:18:57,886 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.core.log.LogFormatUtils: "ERROR" dispatch for POST "/error", parameters={}
2021-08-18 10:18:57,889 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper: Did not store anonymous SecurityContext
2021-08-18 10:18:57,889 WARN [https-jsse-nio-8443-exec-5] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver: Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
2021-08-18 10:18:57,889 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.web.servlet.FrameworkServlet: Exiting from "ERROR" dispatch, status 405
2021-08-18 10:18:57,890 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper: Did not store anonymous SecurityContext
2021-08-18 10:18:57,890 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.SecurityContextPersistenceFilter: Cleared SecurityContextHolder to complete request
2021-08-18 10:18:57,891 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Disabling the response for further output
2021-08-18 10:18:57,894 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Before fill(): parsingHeader: [true], parsingRequestLine: [true], parsingRequestLinePhase: [0], parsingRequestLineStart: [0], byteBuffer.position(): [0], byteBuffer.limit(): [0], end: [618]
2021-08-18 10:18:57,894 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@bc2db3b:org.apache.tomcat.util.net.SecureNioChannel@3e54873f:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:64732]], Read from buffer: [0]
2021-08-18 10:18:57,894 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@bc2db3b:org.apache.tomcat.util.net.SecureNioChannel@3e54873f:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:64732]], Read direct from socket: [0]
2021-08-18 10:18:57,894 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Received []
2021-08-18 10:18:57,895 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@bc2db3b:org.apache.tomcat.util.net.SecureNioChannel@3e54873f:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:64732]], Status in: [OPEN_READ], State out: [OPEN]
2021-08-18 10:18:57,895 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Pushed Processor [org.apache.coyote.http11.Http11Processor@cdb384c]
2021-08-18 10:18:57,895 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Registered read interest for [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@bc2db3b:org.apache.tomcat.util.net.SecureNioChannel@3e54873f:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:64732]]
我发现人们得到 403 而不是 405 的问题,我查看了 this Baeldung page,它似乎表明它应该转到请求的入口点。我已经尝试验证我的 JSESSION id,然后转到 VERIFY_BADGE_URL,但我仍然获得 405 状态。
任何指导将不胜感激!
感谢@neofelis 的回复,他提到 /error 页面不支持 post 请求。
这让我想到我只有一个@GetMapping 方法。所以当然 POST 方法命中 /error 并且不支持 post 导致此错误。
我通过将以下方法添加到错误控制器来修复此问题。
@PostMapping("/error")
@ResponseBody
public String handlePostError(HttpServletRequest request) {
int status = getResponseStatus(request);
if (status == HttpStatus.FORBIDDEN.value()) {
return "uh uh uh, you didn't say the magic word ;)";
}
return "Well..... That doesn't seem right :/";
}
private int getResponseStatus(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
return Integer.parseInt(status.toString());
}
return -1;
}
在
但是,我遇到了 spring 没有返回正确的 Http 响应状态的问题。
这是我重写的配置方法
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> map = new LinkedHashMap<>();
map.put(new AntPathRequestMatcher(WELCOME_PAGE), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(FOOD_SELECTION_PAGE + "/**"), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(CHECKOUT_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(VERIFY_BADGE_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(VERIFY_NAME_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(ADMIN_PAGE), new LoginUrlAuthenticationEntryPoint(LOGIN_PAGE));
map.put(new AntPathRequestMatcher(NEW_FOOD_PAGE), new LoginUrlAuthenticationEntryPoint(LOGIN_PAGE));
map.put(new AntPathRequestMatcher(EDIT_FOOD_URL + "/**"), new LoginUrlAuthenticationEntryPoint(LOGIN_PAGE));
map.put(new AntPathRequestMatcher(HIDE_FOOD_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(SHOW_FOOD_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(DELETE_FOOD_URL), new Http403ForbiddenEntryPoint());
map.put(new AntPathRequestMatcher(REFRESH_EMPS_URL), new Http403ForbiddenEntryPoint());
http.authorizeRequests()
.antMatchers(WELCOME_PAGE,
FOOD_SELECTION_PAGE + "/**",
CHECKOUT_URL,
VERIFY_BADGE_URL,
VERIFY_NAME_URL).denyAll()
.antMatchers(ADMIN_PAGE,
NEW_FOOD_PAGE,
EDIT_FOOD_URL + "/**",
HIDE_FOOD_URL,
SHOW_FOOD_URL,
DELETE_FOOD_URL,
REFRESH_EMPS_URL).hasAnyAuthority("ROLES_USER")
.anyRequest().permitAll()
.and().formLogin().loginPage(LOGIN_PAGE)
.usernameParameter("username")
.passwordParameter("pin")
.defaultSuccessUrl(ADMIN_PAGE)
.permitAll()
.failureUrl(LOGIN_PAGE + "?badlogin")
.and().exceptionHandling().authenticationEntryPoint(new DelegatingAuthenticationEntryPoint(map));
}
我正在使用 postman 执行对 VERIFY_BADGE_URL 的 post 请求。如这些日志中所示,DelegatingAuthenticationEntryPoint 正确地将此请求映射到 Http403ForbiddenEntryPoint
2021-08-18 10:18:57,879 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint: Match found! Executing org.springframework.security.web.authentication.Http403ForbiddenEntryPoint@8f8351a
2021-08-18 10:18:57,879 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.authentication.Http403ForbiddenEntryPoint: Pre-authenticated entry point called. Rejecting access
然后在进一步处理后,我注意到它最终被转换为 405 状态并返回给 postman,如这些日志中所见。
2021-08-18 10:18:57,880 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper: Did not store empty SecurityContext
2021-08-18 10:18:57,881 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper: Did not store empty SecurityContext
2021-08-18 10:18:57,881 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.SecurityContextPersistenceFilter: Cleared SecurityContextHolder to complete request
2021-08-18 10:18:57,881 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Processing ErrorPage[errorCode=0, location=/error]
2021-08-18 10:18:57,884 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.FilterChainProxy: Securing POST /error
2021-08-18 10:18:57,884 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.SecurityContextPersistenceFilter: Set SecurityContextHolder to empty SecurityContext
2021-08-18 10:18:57,884 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.authentication.AnonymousAuthenticationFilter: Set SecurityContextHolder to anonymous SecurityContext
2021-08-18 10:18:57,884 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.FilterChainProxy$VirtualFilterChain: Secured POST /error
2021-08-18 10:18:57,886 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.core.log.LogFormatUtils: "ERROR" dispatch for POST "/error", parameters={}
2021-08-18 10:18:57,889 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper: Did not store anonymous SecurityContext
2021-08-18 10:18:57,889 WARN [https-jsse-nio-8443-exec-5] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver: Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
2021-08-18 10:18:57,889 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.web.servlet.FrameworkServlet: Exiting from "ERROR" dispatch, status 405
2021-08-18 10:18:57,890 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper: Did not store anonymous SecurityContext
2021-08-18 10:18:57,890 DEBUG [https-jsse-nio-8443-exec-5] org.springframework.security.web.context.SecurityContextPersistenceFilter: Cleared SecurityContextHolder to complete request
2021-08-18 10:18:57,891 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Disabling the response for further output
2021-08-18 10:18:57,894 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Before fill(): parsingHeader: [true], parsingRequestLine: [true], parsingRequestLinePhase: [0], parsingRequestLineStart: [0], byteBuffer.position(): [0], byteBuffer.limit(): [0], end: [618]
2021-08-18 10:18:57,894 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@bc2db3b:org.apache.tomcat.util.net.SecureNioChannel@3e54873f:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:64732]], Read from buffer: [0]
2021-08-18 10:18:57,894 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@bc2db3b:org.apache.tomcat.util.net.SecureNioChannel@3e54873f:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:64732]], Read direct from socket: [0]
2021-08-18 10:18:57,894 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Received []
2021-08-18 10:18:57,895 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@bc2db3b:org.apache.tomcat.util.net.SecureNioChannel@3e54873f:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:64732]], Status in: [OPEN_READ], State out: [OPEN]
2021-08-18 10:18:57,895 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Pushed Processor [org.apache.coyote.http11.Http11Processor@cdb384c]
2021-08-18 10:18:57,895 DEBUG [https-jsse-nio-8443-exec-5] org.apache.juli.logging.DirectJDKLog: Registered read interest for [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@bc2db3b:org.apache.tomcat.util.net.SecureNioChannel@3e54873f:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:64732]]
我发现人们得到 403 而不是 405 的问题,我查看了 this Baeldung page,它似乎表明它应该转到请求的入口点。我已经尝试验证我的 JSESSION id,然后转到 VERIFY_BADGE_URL,但我仍然获得 405 状态。
任何指导将不胜感激!
感谢@neofelis 的回复,他提到 /error 页面不支持 post 请求。
这让我想到我只有一个@GetMapping 方法。所以当然 POST 方法命中 /error 并且不支持 post 导致此错误。
我通过将以下方法添加到错误控制器来修复此问题。
@PostMapping("/error")
@ResponseBody
public String handlePostError(HttpServletRequest request) {
int status = getResponseStatus(request);
if (status == HttpStatus.FORBIDDEN.value()) {
return "uh uh uh, you didn't say the magic word ;)";
}
return "Well..... That doesn't seem right :/";
}
private int getResponseStatus(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
return Integer.parseInt(status.toString());
}
return -1;
}