SecurityFilterChain .anyRequest().permitAll() 不允许 POST 个请求
SecurityFilterChain .anyRequest().permitAll() doesn't allow POST requests
使用 Spring Boot 2.7 (Spring Security 5.7.1) 并尝试将 API 配置为资源服务器和 OAuth2 客户端我发现了一个我不明白的行为了解:
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.mvcMatchers("/swagger-ui/**", "/api-docs/**").permitAll()
.anyRequest().permitAll())
// register OAuth2 resource server
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
// register OAuth2 client
.oauth2Client(withDefaults());
return http.build();
}
}
检查日志,所有这些过滤器都适用
o.s.s.web.DefaultSecurityFilterChain : Will secure any request with
org.springframework.security.web.session.DisableEncodeUrlFilter@320ca97c,
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3c592c0c,
org.springframework.security.web.context.SecurityContextPersistenceFilter@2b33e616,
org.springframework.security.web.header.HeaderWriterFilter@2e9bff08,
org.springframework.security.web.csrf.CsrfFilter@7926d092,
org.springframework.security.web.authentication.logout.LogoutFilter@37227aa7,
org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@6f18445b,
org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter@42af2977,
org.springframework.security.web.savedrequest.RequestCacheAwareFilter@79e3f444, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@1252d480,
org.springframework.security.web.authentication.AnonymousAuthenticationFilter@3979c6e8,
org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter@19faa9dc,
org.springframework.security.web.session.SessionManagementFilter@7d3b4646,
org.springframework.security.web.access.ExceptionTranslationFilter@6cb2d5ea,
到目前为止,此配置在我正在保护的其他 API 中按预期工作。但是,在这个特殊的情况下,我看到没有保护任何端点:
我可以访问任何 GET
端点,但任何 POST
端点 returns 和 403 FORBIDDEN
。但是,如果我向请求添加一个令牌,我可以访问它们 即使它是一个过期的令牌
仅这一点我无法理解,因为 .anyRequest().permitAll()
如果我没记错的话,应该取消任何保护。
如果我注释掉配置 oauth2 ResourceServer 的行
`// .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)`
此过滤器消失
org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter
并且不能再使用 POST
个端点,即使令牌已过期
从逻辑上讲,我希望 API 是 oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
所以
我怎么在使用 .anyRequest().permitAll())
时无法访问 POST 端点?
免责声明:我知道如果所有端点都必须是 public,那么将 API 声明为资源服务器是没有意义的。 Discord 回调将访问端点,我必须弄清楚我是否可以使用 OAuth
保护它们
编辑:
server.servlet.context-path = /api
控制器
@RestController
@RequestMapping("/slack")
public class SlackBotController {
@PostMapping("/test")
public String test(@RequestBody String a) {
return a;
}
@GetMapping("/test")
public String testGet() {
return "OK";
}
}
请求
GET/POST http://localhost:8081/api/slack/test
请求headers
User-Agent: PostmanRuntime/7.29.0
Accept: */*
Postman-Token: f20ba7a6-26e5-47c4-a827-0596afec27b8
Host: localhost:8081
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 3
Cookie: JSESSIONID=D1C2B2668DC130C63DDE03F30574ED5F; JSESSIONID=823D79956CFBF14F3C77C96E29F4131C
回应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: application/json
Transfer-Encoding: chunked
Date: Fri, 03 Jun 2022 12:03:00 GMT
Keep-Alive: timeout=60
Connection: keep-alive
这里的问题是CSRF保护。当您使用 http.oauth2ResourceServer()
Spring 安全配置 CSRF 以忽略包含 header Authorization: Bearer whatever
的请求时,请注意它必须包含 Bearer
前缀。
在您共享的请求示例中,您没有包括授权 header。
在 Spring 安全性中查看 at the code。
之所以POST
端点或POST
returns一个403 FORBIDDEN
是因为spring中默认启用了CSRF保护。
这意味着每个 修改 请求(POST、PUT、DELETE、PATCH)都需要一个 CSRF 令牌。否则请求将被拒绝以防止 CSRF 攻击。
要禁用 CSRF 保护:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable();
}
使用 Spring Boot 2.7 (Spring Security 5.7.1) 并尝试将 API 配置为资源服务器和 OAuth2 客户端我发现了一个我不明白的行为了解:
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.mvcMatchers("/swagger-ui/**", "/api-docs/**").permitAll()
.anyRequest().permitAll())
// register OAuth2 resource server
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
// register OAuth2 client
.oauth2Client(withDefaults());
return http.build();
}
}
检查日志,所有这些过滤器都适用
o.s.s.web.DefaultSecurityFilterChain : Will secure any request with
org.springframework.security.web.session.DisableEncodeUrlFilter@320ca97c,
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3c592c0c,
org.springframework.security.web.context.SecurityContextPersistenceFilter@2b33e616,
org.springframework.security.web.header.HeaderWriterFilter@2e9bff08,
org.springframework.security.web.csrf.CsrfFilter@7926d092,
org.springframework.security.web.authentication.logout.LogoutFilter@37227aa7,
org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@6f18445b,
org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter@42af2977,
org.springframework.security.web.savedrequest.RequestCacheAwareFilter@79e3f444, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@1252d480,
org.springframework.security.web.authentication.AnonymousAuthenticationFilter@3979c6e8,
org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter@19faa9dc,
org.springframework.security.web.session.SessionManagementFilter@7d3b4646,
org.springframework.security.web.access.ExceptionTranslationFilter@6cb2d5ea,
到目前为止,此配置在我正在保护的其他 API 中按预期工作。但是,在这个特殊的情况下,我看到没有保护任何端点:
我可以访问任何 GET
端点,但任何 POST
端点 returns 和 403 FORBIDDEN
。但是,如果我向请求添加一个令牌,我可以访问它们 即使它是一个过期的令牌
仅这一点我无法理解,因为 .anyRequest().permitAll()
如果我没记错的话,应该取消任何保护。
如果我注释掉配置 oauth2 ResourceServer 的行
`// .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)`
此过滤器消失
org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter
并且不能再使用 POST
个端点,即使令牌已过期
从逻辑上讲,我希望 API 是 oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
所以
我怎么在使用 .anyRequest().permitAll())
时无法访问 POST 端点?
免责声明:我知道如果所有端点都必须是 public,那么将 API 声明为资源服务器是没有意义的。 Discord 回调将访问端点,我必须弄清楚我是否可以使用 OAuth
保护它们编辑:
server.servlet.context-path = /api
控制器
@RestController
@RequestMapping("/slack")
public class SlackBotController {
@PostMapping("/test")
public String test(@RequestBody String a) {
return a;
}
@GetMapping("/test")
public String testGet() {
return "OK";
}
}
请求
GET/POST http://localhost:8081/api/slack/test
请求headers
User-Agent: PostmanRuntime/7.29.0
Accept: */*
Postman-Token: f20ba7a6-26e5-47c4-a827-0596afec27b8
Host: localhost:8081
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 3
Cookie: JSESSIONID=D1C2B2668DC130C63DDE03F30574ED5F; JSESSIONID=823D79956CFBF14F3C77C96E29F4131C
回应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: application/json
Transfer-Encoding: chunked
Date: Fri, 03 Jun 2022 12:03:00 GMT
Keep-Alive: timeout=60
Connection: keep-alive
这里的问题是CSRF保护。当您使用 http.oauth2ResourceServer()
Spring 安全配置 CSRF 以忽略包含 header Authorization: Bearer whatever
的请求时,请注意它必须包含 Bearer
前缀。
在您共享的请求示例中,您没有包括授权 header。
在 Spring 安全性中查看 at the code。
之所以POST
端点或POST
returns一个403 FORBIDDEN
是因为spring中默认启用了CSRF保护。
这意味着每个 修改 请求(POST、PUT、DELETE、PATCH)都需要一个 CSRF 令牌。否则请求将被拒绝以防止 CSRF 攻击。
要禁用 CSRF 保护:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable();
}