即使端点设置为 permitAll,也会检查不记名令牌
Bearer token is checked even if endpoint is set to permitAll
我正在使用 spring-security-oauth2-provider:3.0.0-RC2
和 Grails 3.2.1
。所有资源端点都以 /api
开头,使用
"/api/$controller/$action?/$id?(.$format)?" {
constraints {
}
}
这是过滤器链图(与文档中给出的相同):
String tokenFilters = "JOINED_FILTERS,-oauth2ProviderFilter,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-exceptionTranslationFilter"
String securedResourcesFilter = "JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-oauth2BasicAuthenticationFilter,-exceptionTranslationFilter"
String otherFilters = "JOINED_FILTERS,-statelessSecurityContextPersistenceFilter,-oauth2ProviderFilter,-clientCredentialsTokenEndpointFilter,-oauth2BasicAuthenticationFilter,-oauth2ExceptionTranslationFilter"
grails.plugin.springsecurity.filterChain.chainMap = [
[pattern: "/api/oauth/token", filters: tokenFilters],
[pattern: "/api/**", filters: securedResourcesFilter],
[pattern: "/**", filters: otherFilters]
]
我正在使用密码授予身份验证,只要令牌在浏览器的本地存储中可用,通过传递 Authorization
header 一切正常。
我将不记名令牌存储在浏览器的本地存储中。问题是当令牌过期并且在浏览器的本地存储中仍然可用时。其中一个动作被标记为 @Secured(["permitAll"])
所以当我点击那个动作时(并且过期的 Authorization
header 也被传递),请求被 401 拒绝,因为令牌是已过期。
这是设计使然,即使端点或 controller/action 设置为 permitAll
,spring 安全性仍将检查访问令牌的有效性(如果可用)?
是的,我相信 401
响应是设计使然。
您描述的是 OAuth2AuthenticationProcessingFilter
的行为。过滤器 attempts to extract the token from the request and upon finding one it attempts to authenticate it. If the authentication fails for some reason (like an expired token), the filter will treat it as an Authentication failure。
因为 OAuth2AuthenticationProcessingFilter
在 filter-chain 中处于较高位置,所以在请求有机会进入较低级别并根据控制器做出决定之前,它会在无效令牌上终止请求注释。
基本上,如果您出示访问令牌,应用程序将尝试对其进行身份验证。
解决方法
当您从 spring-security-oauth2-provider 获取访问令牌时,它通常包含一些可以在客户端中检查的过期信息,以防止过期的授权 header 在第一名。您也可以考虑使用 Refresh Token Grant.
如果更改客户端不起作用,您可以配置 filterChain.chainMap
,以便您尝试允许的控制器操作的 uri 使用 otherFilters
,如下所示:
grails.plugin.springsecurity.filterChain.chainMap = [
[pattern: "/api/oauth/token", filters: tokenFilters],
[pattern: "/api/foo/myControllerActionThatIsPermitAll", filters: otherFilters],
[pattern: "/api/**", filters: securedResourcesFilter],
[pattern: "/**", filters: otherFilters]
]
请注意,a github issue reported on spring-security-oauth 描述了您的问题。
我正在使用 spring-security-oauth2-provider:3.0.0-RC2
和 Grails 3.2.1
。所有资源端点都以 /api
开头,使用
"/api/$controller/$action?/$id?(.$format)?" {
constraints {
}
}
这是过滤器链图(与文档中给出的相同):
String tokenFilters = "JOINED_FILTERS,-oauth2ProviderFilter,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-exceptionTranslationFilter"
String securedResourcesFilter = "JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-oauth2BasicAuthenticationFilter,-exceptionTranslationFilter"
String otherFilters = "JOINED_FILTERS,-statelessSecurityContextPersistenceFilter,-oauth2ProviderFilter,-clientCredentialsTokenEndpointFilter,-oauth2BasicAuthenticationFilter,-oauth2ExceptionTranslationFilter"
grails.plugin.springsecurity.filterChain.chainMap = [
[pattern: "/api/oauth/token", filters: tokenFilters],
[pattern: "/api/**", filters: securedResourcesFilter],
[pattern: "/**", filters: otherFilters]
]
我正在使用密码授予身份验证,只要令牌在浏览器的本地存储中可用,通过传递 Authorization
header 一切正常。
我将不记名令牌存储在浏览器的本地存储中。问题是当令牌过期并且在浏览器的本地存储中仍然可用时。其中一个动作被标记为 @Secured(["permitAll"])
所以当我点击那个动作时(并且过期的 Authorization
header 也被传递),请求被 401 拒绝,因为令牌是已过期。
这是设计使然,即使端点或 controller/action 设置为 permitAll
,spring 安全性仍将检查访问令牌的有效性(如果可用)?
是的,我相信 401
响应是设计使然。
您描述的是 OAuth2AuthenticationProcessingFilter
的行为。过滤器 attempts to extract the token from the request and upon finding one it attempts to authenticate it. If the authentication fails for some reason (like an expired token), the filter will treat it as an Authentication failure。
因为 OAuth2AuthenticationProcessingFilter
在 filter-chain 中处于较高位置,所以在请求有机会进入较低级别并根据控制器做出决定之前,它会在无效令牌上终止请求注释。
基本上,如果您出示访问令牌,应用程序将尝试对其进行身份验证。
解决方法
当您从 spring-security-oauth2-provider 获取访问令牌时,它通常包含一些可以在客户端中检查的过期信息,以防止过期的授权 header 在第一名。您也可以考虑使用 Refresh Token Grant.
如果更改客户端不起作用,您可以配置 filterChain.chainMap
,以便您尝试允许的控制器操作的 uri 使用 otherFilters
,如下所示:
grails.plugin.springsecurity.filterChain.chainMap = [
[pattern: "/api/oauth/token", filters: tokenFilters],
[pattern: "/api/foo/myControllerActionThatIsPermitAll", filters: otherFilters],
[pattern: "/api/**", filters: securedResourcesFilter],
[pattern: "/**", filters: otherFilters]
]
请注意,a github issue reported on spring-security-oauth 描述了您的问题。