CORS 干扰 Spring Security oauth2

Posted

技术标签:

【中文标题】CORS 干扰 Spring Security oauth2【英文标题】:CORS interfering with Spring Security oauth2 【发布时间】:2017-11-09 15:56:20 【问题描述】:

我在尝试从浏览器的 oauth/token 获取令牌时遇到问题。我有一个带有 Spring Security 和 Spring Security oauth 的 Spring Boot 应用程序,我正在尝试从不同端口中的 javascript SPA 进行身份验证。

当在后端禁用 CORS 时,我可以使用 Postman 或终端从 oauth 端点获取令牌,但由于 CORS 预检失败,我无法从 javascript 获取它们。

如果我启用 CORS,预检会成功,但现在我收到 InsufficientAuthenticationException,说 “没有客户端身份验证。尝试添加适当的身份验证过滤器”。据我所知,这是因为 Spring Security 无法从请求中获取主体。

有人对如何处理这个问题有建议吗?

【问题讨论】:

当您从其他域发送请求时,CORS 会阻止 OPTIONS 的飞行前请求。所以在你的控制器代码中添加@CrossOrigin@RestController并检查一次。 @Hema 是的,这是我的问题,当我添加 CORS(在每个端点上)时,我得到了 InsufficientAuthenticationException。我应该添加一个 @RestController 包含 spring 自动创建的 oauth 端点,还是会覆盖 spring 安全性? 不,那不会超车。只需添加@RestController 并尝试一次。这对我来说很好。所以建议你 【参考方案1】:

显然 Oauth2 端点和过滤器在进入 Spring Security 过滤器链之前得到处理,因此添加 CORS 过滤器通常不起作用,但添加具有高优先级的 CORS 过滤器 bean 最终会起作用。

这是我的 CORS 专用配置类(改编自官方 spring 指南,我稍后会对其进行调整)

@Configuration
public class CorsConfig 
//IMPORTANT: it has to be a normal configuration class, 
//not extending WebMvcConfigurerAdapter or other Spring Security class
    @Bean
    public FilterRegistrationBean customCorsFilter() 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://localhost:3000");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));

        //IMPORTANT #2: I didn't stress enough the importance of this line in my original answer, 
        //but it's here where we tell Spring to load this filter at the right point in the chain
        //(with an order of precedence higher than oauth2's filters)
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    

【讨论】:

我使用的是 spring 4.3 版本,您的代码在我的情况下显示错误,例如 FilterRegistrationBean 无法解析为类型。 @sireeshaj 自发布以来我基本上没有接触过这段代码,它仍在工作。我刚刚将方法名称从corsFilter 更改为customCorsFilter,因为spring 抱怨(因为spring boot 已经用该名称定义了自己的bean),也许试试?否则我的代码看起来像上面的代码,并且在 spring boot 1.5.12 上运行良好(使用 spring 4.3.16) 对于这个问题,我必须至少查看 20 个不同的“答案”,其中包含您发布的答案的多个版本。他们中没有一个人使用 bea,.setOrder(Ordered.HIGHEST_PRECEDENCE) 这正是我的问题。我花了几个小时才得到你的答案,但我很高兴我找到了它。谢谢! @spetz83 很好,我已经忘记了那个细节的重要性,但它确实是 sn-p 中最关键的部分。我已经更新了强调这一事实的答案,谢谢 你先生!我也搜索了一半的互联网,最后。非常感谢。【参考方案2】:

如果您使用的是 Spring boot 2,只需更新 SrThompson 的响应,FilterRegistrationBean 类现在是通用的。

所以代码看起来像这样:

@Configuration
public class CorsConfig 

    @Bean
    public FilterRegistrationBean<CorsFilter> customCorsFilter() 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.setAllowedMethods(Collections.singletonList("*"));
        config.setAllowedHeaders(Collections.singletonList("*"));
        config.addAllowedOrigin("http://localhost:3000");
        config.addAllowedOrigin("http://production.url");
        config.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));

        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    

【讨论】:

以上是关于CORS 干扰 Spring Security oauth2的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security CORS 不工作

Spring-Security:使用 CORS Preflights 获得 401(尽管 http.cors())

Spring-security 的 CORS 问题

Spring Security CORS:来源已被 CORS 策略阻止

CORS与CSRF在Spring Security中的使用

Spring Security Logout 不适用于 Spring 4 CORS