Spring Boot 和 OAuth2 CORS
Posted
技术标签:
【中文标题】Spring Boot 和 OAuth2 CORS【英文标题】:Spring Boot and OAuth2 CORS 【发布时间】:2017-05-13 13:13:12 【问题描述】:当我们使用 axios 客户端从节点服务器访问 api 时,总是会遇到以下错误:
XMLHttpRequest cannot load http://localhost:8089/public/api. Redirect from 'http://localhost:8089/public/api/' to 'http://localhost:8089/' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3002' is therefore not allowed access.
我的配置如下:
import java.security.Principal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.catalina.filters.CorsFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.filter.CompositeFilter;
@SpringBootApplication
@EnableOAuth2Client
@EnableAuthorizationServer
@Order(6)
public class MonitoringApiApplication extends WebSecurityConfigurerAdapter
@Autowired
OAuth2ClientContext oauth2ClientContext;
@Override
protected void configure(HttpSecurity http) throws Exception
// @formatter:off
http
.antMatcher("/**").authorizeRequests().antMatchers("/","/user**", "/login**", "/webjars/**").permitAll().anyRequest()
.authenticated().and().exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/")).and().logout()
.logoutSuccessUrl("/").permitAll().and().csrf().disable()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
// @formatter:on
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
@Override
public void configure(HttpSecurity http) throws Exception
// @formatter:off
http.antMatcher("/me").authorizeRequests().anyRequest().authenticated();
// @formatter:on
public static void main(String[] args)
SpringApplication.run(MonitoringApiApplication.class, args);
@Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter)
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
@Bean
@ConfigurationProperties("github")
public ClientResources github()
return new ClientResources();
@Bean
@ConfigurationProperties("facebook")
public ClientResources facebook()
return new ClientResources();
private Filter ssoFilter()
CompositeFilter filter = new CompositeFilter();
List<Filter> filters = new ArrayList<>();
filters.add(ssoFilter(facebook(), "/login/facebook"));
filters.add(ssoFilter(github(), "/login/github"));
filter.setFilters(filters);
return filter;
private Filter ssoFilter(ClientResources client, String path)
OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationFilter = new OAuth2ClientAuthenticationProcessingFilter(
path);
OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
oAuth2ClientAuthenticationFilter.setRestTemplate(oAuth2RestTemplate);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(),
client.getClient().getClientId());
tokenServices.setRestTemplate(oAuth2RestTemplate);
oAuth2ClientAuthenticationFilter.setTokenServices(tokenServices);
return oAuth2ClientAuthenticationFilter;
class ClientResources
@NestedConfigurationProperty
private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();
@NestedConfigurationProperty
private ResourceServerProperties resource = new ResourceServerProperties();
public AuthorizationCodeResourceDetails getClient()
return client;
public ResourceServerProperties getResource()
return resource;
过滤器配置:
@Bean
public FilterRegistrationBean corsFilter()
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:3002");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
春季开机版本:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
如果我将 /public/** 添加到 antMatchers 它可以工作,这意味着端点不受 ssoFilter() 保护,我已经尝试过将虚假来源的凭据设置为 * 但没有任何工作
【问题讨论】:
可能是***.com/questions/35035055/spring-boot-and-cors?rq=1对你有帮助 【参考方案1】:对我来说,唯一有效的解决方案来自此链接:
Spring security, cors error when enable Oauth2
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@WebFilter("/*") //TODO Exclude API endpoints when possible
public class CorsFilter implements Filter
public CorsFilter()
@Override
public void init(FilterConfig fc)
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException
System.out.println("doFilter");
HttpServletResponse response = (HttpServletResponse) resp;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response
.setHeader("Access-Control-Allow-Headers", "Origin, origin, x-requested-with, authorization, " +
"Content-Type, Authorization, credential, X-XSRF-TOKEN");
if ("OPTIONS".equalsIgnoreCase(request.getMethod()))
response.setStatus(HttpServletResponse.SC_OK);
else
chain.doFilter(req, resp);
@Override
public void destroy()
我还需要从扩展 WebSecurityConfigurerAdapter 和 ResourceServerConfigurerAdapter 的类的配置方法中删除 http.cors()。
【讨论】:
【参考方案2】:你需要添加这个http.cors().and().csrf().disable();以及 SecurityConfig 文件中的过滤器。
@Bean
CorsConfigurationSource corsConfigurationSource()
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
您需要最新版本的 spring security 之一才能正常工作。
【讨论】:
在完成所有文档、***、google 示例之后,这是为我启用 CORS 的唯一想法。以上是关于Spring Boot 和 OAuth2 CORS的主要内容,如果未能解决你的问题,请参考以下文章
带有 Google 的 OAuth2 - CORS 错误(Angular + Spring boot)[重复]
Spring boot Oauth2 + Angular CORS问题
spring boot with react前端oauth2代理CORS问题
如何在 Spring Boot 2.x 中将 CORS 添加到 oauth2/resource 服务器?