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

Spring-Security OAuth2 设置 - 无法找到 oauth2 命名空间处理程序

Spring Security OAuth2 v5:NoSuchBeanDefinitionException:'org.springframework.security.oauth2.jwt.Jwt

针对授权标头的Spring Security OAuth2 CORS问题

OAuth2.0学习(4-1)Spring Security OAuth2.0 - 代码分析