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 Preflights 获得 401(尽管 http.cors())