Spring Security OAuth2 始终重定向到具有有效 Bearer 标头的 /login 页面
Posted
技术标签:
【中文标题】Spring Security OAuth2 始终重定向到具有有效 Bearer 标头的 /login 页面【英文标题】:Spring Security OAuth2 always redirects to /login page having a valid Bearer header 【发布时间】:2017-09-04 15:19:55 【问题描述】:我很难让 Spring Security OAuth2 正常工作。我能够从 /oauth/token 端点获取 access_token,但使用标头“授权:承载 $TOKEN”中的该令牌访问受保护的资源总是将我重定向到 /login。这是一个完整的 REST API。
OAuth2Config
@Configuration
public class OAuth2Configuration
private static final String SERVER_RESOURCE_ID = "oauth2-server";
private static InMemoryTokenStore tokenStore = new InMemoryTokenStore();
@Configuration
@EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception
resources.tokenStore(tokenStore).resourceId(SERVER_RESOURCE_ID);
@Override
public void configure(HttpSecurity http) throws Exception
http.requestMatchers().antMatchers("/admin**").and().authorizeRequests().antMatchers("/admin**").access("#oauth2.hasScope('read')");
@Configuration
@EnableAuthorizationServer
protected static class AuthConfig extends AuthorizationServerConfigurerAdapter
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception
endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).approvalStoreDisabled();
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
clients.inMemory()
.withClient("my-client")
.authorizedGrantTypes("authorization_code","refresh_token", "password")
.authorities("ROLE_CLIENT")
.scopes("read")
.resourceIds(SERVER_RESOURCE_ID)
.secret("secret")
;
SecurityConfig 类
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
return new BCryptPasswordEncoder();
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
auth
.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder());
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
以下是调试日志
2017-04-10 10:58:31.634[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Initializing servlet 'dispatcherServlet'
[2m2017-04-10 10:58:31.635[0;39m [32m INFO[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.a.c.c.C.[Tomcat].[localhost].[/] [0;39m [2m:[0;39m Initializing Spring FrameworkServlet 'dispatcherServlet'
[2m2017-04-10 10:58:31.635[0;39m [32m INFO[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m FrameworkServlet 'dispatcherServlet': initialization started
[2m2017-04-10 10:58:31.635[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Using MultipartResolver [org.springframework.web.multipart.support.StandardServletMultipartResolver@40aad17d]
[2m2017-04-10 10:58:31.639[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Unable to locate LocaleResolver with name 'localeResolver': using default [org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver@70f4e8c6]
[2m2017-04-10 10:58:31.643[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Unable to locate ThemeResolver with name 'themeResolver': using default [org.springframework.web.servlet.theme.FixedThemeResolver@201a4016]
[2m2017-04-10 10:58:31.649[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Unable to locate RequestToViewNameTranslator with name 'viewNameTranslator': using default [org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@5f14eeee]
[2m2017-04-10 10:58:31.656[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Unable to locate FlashMapManager with name 'flashMapManager': using default [org.springframework.web.servlet.support.SessionFlashMapManager@1688575]
[2m2017-04-10 10:58:31.656[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Published WebApplicationContext of servlet 'dispatcherServlet' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcherServlet]
[2m2017-04-10 10:58:31.656[0;39m [32m INFO[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m FrameworkServlet 'dispatcherServlet': initialization completed in 21 ms
[2m2017-04-10 10:58:31.656[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Servlet 'dispatcherServlet' configured successfully
[2m2017-04-10 10:58:31.692[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m DispatcherServlet with name 'dispatcherServlet' processing POST request for [/oauth/token]
[2m2017-04-10 10:58:31.695[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36ms.w.s.m.m.a.RequestMappingHandlerMapping[0;39m [2m:[0;39m Looking up handler method for path /oauth/token
[2m2017-04-10 10:58:31.699[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36ms.w.s.m.m.a.RequestMappingHandlerMapping[0;39m [2m:[0;39m Did not find handler method for [/oauth/token]
[2m2017-04-10 10:58:32.012[0;39m [32m INFO[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.s.o.p.token.store.JdbcTokenStore [0;39m [2m:[0;39m Failed to find access token for token 7c74f287-e187-4228-b0c2-b79972f9b89b
[2m2017-04-10 10:58:32.226[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.w.s.m.m.a.HttpEntityMethodProcessor [0;39m [2m:[0;39m Written [7c74f287-e187-4228-b0c2-b79972f9b89b] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@2fd4312a]
[2m2017-04-10 10:58:32.226[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
[2m2017-04-10 10:58:32.226[0;39m [32mDEBUG[0;39m [35m6456[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Successfully completed request
我错过了什么?我几乎已经通过网络尝试了每个示例到我现有的项目中,但是当我尝试使用有效令牌请求受保护的资源时,我总是被重定向到 /login 端点。
谢谢。
【问题讨论】:
您使用的是哪种身份验证流程?另外,您有任何用户可以登录吗?密码和身份验证代码需要用户凭据,我假设您正在使用这些凭据,因为您的代码中未列出 client_credentials 流程 我正在使用密码流。我有用户可以登录,我可以成功地从 oauth/token 获取 access_token,但是在访问受保护的资源时,我总是得到一个带有位置 /login 的 HTTP 302 响应。 【参考方案1】:原来我是从早期版本的spring boot升级到1.5.2,所以在release notes中说资源过滤器的顺序发生了变化。 See here。只需将这个神奇的属性放在 application.properties 文件中,它就会修复所有问题。
security.oauth2.resource.filter-order = 3
OAuth2 资源过滤器的默认顺序已从 3 更改为 SecurityProperties.ACCESS_OVERRIDE_ORDER - 1。这将其放置在执行器端点之后,但在基本身份验证过滤器链之前。可以通过设置 security.oauth2.resource.filter-order = 3 来恢复默认值。
【讨论】:
谢谢,我也遇到了同样的问题(Spring 1.5.4),添加这有助于达到终点。以上是关于Spring Security OAuth2 始终重定向到具有有效 Bearer 标头的 /login 页面的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security 入门(1-3)Spring Security oauth2.0 指南
Spring-Security OAuth2 设置 - 无法找到 oauth2 命名空间处理程序
Spring Security OAuth2 v5:NoSuchBeanDefinitionException:'org.springframework.security.oauth2.jwt.Jwt