如何使用密码授予在 Spring Boot Oauth2 资源服务器中处理 CORS

Posted

技术标签:

【中文标题】如何使用密码授予在 Spring Boot Oauth2 资源服务器中处理 CORS【英文标题】:How do I handle CORS in Spring Boot Oauth2 Resource Server with password grant 【发布时间】:2020-11-26 20:05:41 【问题描述】:

详情: 我正在使用 spring boot oauth2 资源服务器,即使在尝试了不同的方法来过滤它之后,它也会给我 CORS。

我的代码看起来如何?

它是一个简单的资源服务器,带有 spring-cloud-starter-oauth2spring-cloud-starter-security 作为两个主要依赖项的 Spring Boot。

我已使用 java 注释将其设为资源服务器:

@CrossOrigin(origins = "*", maxAge = 3600, allowedHeaders = "*")
@RestController
@RequestMapping("/api/v1")
@EnableResourceServer

这是我尝试解决此问题的方法:

我尝试添加一个自定义过滤器,该过滤器使用下面的代码跳过进一步的过滤器调用。在此之后,我得到“Authorization Header not allowed in preflight request on browser”。将CORS everyehere 扩展添加到我的浏览器后,我的请求成功了。

@EnableWebSecurity(debug = true)
@Order(Ordered.HIGHEST_PRECEDENCE)
public class WebSecurityConfig implements Filter 

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        response.setHeader("Access-Control-Expose-Headers", "Location");
        System.out.println(request.getMethod());
        System.out.println("-----------------");
        if(!request.getMethod().equals("OPTIONS")) 
            chain.doFilter(req, res);
        
    

    @Override
    public void init(FilterConfig filterConfig) 

    @Override
    public void destroy() 


【问题讨论】:

【参考方案1】:

我也遇到了同样的问题 这就是决议。

public class ResourceServerCustom extends ResourceServerConfigurerAdapter 

@Override
public void configure(HttpSecurity http) throws Exception 
    http.csrf().disable().cors().disable().authorizeRequests().antMatchers("/oauth/token/**").permitAll()
            .anyRequest().authenticated().and().exceptionHandling()
            .authenticationEntryPoint(new AuthExceptionEntryPoint());

    http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());


还有其他配置。

public class WebSecurityCustom extends WebSecurityConfigurerAdapter 

public TokenStore tokenStore;

@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception 
    return super.authenticationManager();


@Override
public void configure(WebSecurity web) throws Exception 
    web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**",
            "/configuration/security", "/swagger-ui.html", "/webjars/**");
    web.ignoring().antMatchers(HttpMethod.OPTIONS);

public class CorsFilterCustom extends OncePerRequestFilter 

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
        throws ServletException, IOException 
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods",
            "ACL, CANCELUPLOAD, CHECKIN, CHECKOUT, COPY, DELETE, GET, HEAD, LOCK, MKCALENDAR, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, REPORT, SEARCH, UNCHECKOUT, UNLOCK, UPDATE, VERSION-CONTROL");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers",
            "Origin, X-Requested-With, Content-Type, Accept, Key, Authorization");

    if ("OPTIONS".equalsIgnoreCase(request.getMethod())) 
        response.setStatus(HttpServletResponse.SC_OK);
     else 
        chain.doFilter(request, response);
    

public class AuthorizationServerCustom implements AuthorizationServerConfigurer 

@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception 
    security.checkTokenAccess("isAuthenticated()");


@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception 
    endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager);

public class AuthExceptionEntryPoint implements AuthenticationEntryPoint 

@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2)
        throws ServletException, IOException 
    final Map<String, Object> mapBodyException = new HashMap<>();

    mapBodyException.put("error", "Error from AuthenticationEntryPoint");
    mapBodyException.put("message", "Message from AuthenticationEntryPoint");
    mapBodyException.put("exception", "My stack trace exception");
    mapBodyException.put("path", request.getServletPath());
    mapBodyException.put("timestamp", (new Date()).getTime());

    response.setContentType("application/json");
    response.setStatus(HttpServletResponse.SC_FORBIDDEN);

    final ObjectMapper mapper = new ObjectMapper();
    mapper.writeValue(response.getOutputStream(), mapBodyException);

【讨论】:

公共类 ResourceServerCustom 扩展 ResourceServerConfigurerAdapter @Override public void configure(HttpSecurity http) throws Exception http.csrf().disable().cors().disable().authorizeRequests().antMatchers( "/oauth/token/**").permitAll().anyRequest().authenticated().and().exceptionHandling().authenticationEntryPoint(new AuthExceptionEntryPoint()); http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues()); 【参考方案2】:

您可以通过添加具有不同变体的配置类来配置 cors,例如

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter 

  @Override
  protected void configure(HttpSecurity http) throws Exception 
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowedMethods(Collections.singletonList("*"));

    http.cors().configurationSource(request -> config);
  

或者像这样禁用

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter 

  @Override
  protected void configure(HttpSecurity http) throws Exception 
    http.cors().disable();
  

【讨论】:

以上是关于如何使用密码授予在 Spring Boot Oauth2 资源服务器中处理 CORS的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot Oauth2 验证资源所有者密码凭证授予的访问令牌

spring boot oauth2.0 和 spring security:如何通过 facebook 或 slack 授予用户登录权限(权限)

如何使用 Spring Boot + Angular 处理外部 OAuth2 身份验证

带有Angularjs注销错误的Spring Boot

如何使用Azure AD B2C保护Spring Boot REST API?

Spring Boot如何在属性文件中隐藏密码