【问题标题】:How to CORS bypass in Spring?如何在 Spring 中绕过 CORS?
【发布时间】:2019-12-23 21:15:33
【问题描述】:

我使用 RestTemplate 在 Spring Boot 中创建应用程序 - API 客户端。 API(不是我的)可能有 CORS,因为在控制台中我得到 403,但在浏览器/邮递员中是可以的。 如何绕过 CORS?

public Pokemontcg getPokemontcg() {
    RestTemplate restTemplate = new RestTemplate();
    Pokemontcg forObject = restTemplate.getForObject("https://api.pokemontcg.io/v1/cards?name=charizard", Pokemontcg.class);
    return forObject;
}

结果

"main" org.springframework.web.client.HttpClientErrorException$Forbidden: 403 Forbidden

【问题讨论】:

  • 你在哪里得到 CORS 错误?
  • 用一点代码更新你的问题
  • curl 的请求运行良好。您应该检查一次完整的错误响应。 API 正在使用 cloudflare 进行保护。您可能会在以下问题中找到解决方案:stackoverflow.com/questions/54367327/…

标签: spring-boot


【解决方案1】:

有多种方法。最有效的方法之一是 在JavaConfig做它

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

或者最简单的方法是 控制器方法CORS配置 启用 CORS 很简单——只需添加注释 @CrossOrigin。

我们可以通过多种不同的方式实现这一点。

@CrossOrigin 上的 @RequestMapping-Annotated 处理程序方法

@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin
    @RequestMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

如果你想要客户端解决方案,这里就是解决方案

考虑这个例子。

你的服务器是 my-server.com,你的客户端是 my-client.com 配置nginx如下:

// nginx.conf

upstream server {
    server my-server.com;
}

upstream client {
    server my-client.com;
}

server {
    listen 80;

    server_name my-website.com;
    access_log /path/to/access/log/access.log;
    error_log /path/to/error/log/error.log;

    location / {
        proxy_pass http://client;
    }

    location ~ /server/(?<section>.*) {
        rewrite ^/server/(.*)$ /$1 break;
        proxy_pass http://server;
    }
}

这里my-website.com 将是可访问代码的网站的结果名称(代理网站的名称)。一旦nginx 以这种方式配置。您将需要修改请求,以便:

All API calls change from my-server.com/<API-path> to my-website.com/server/<API-path>

【讨论】:

  • 但这不是我的 API。我只创建一个 API 客户端。
  • 是的,您可以简单地更改@requestmapping,因为您的问题中的信息非常少。这是一个非常通用的例子。
  • CORS:跨域资源共享。当您与 2 个不同的服务器交谈时,它就来了。两台服务器都需要相互信任,因此您只需要将 URL 列入白名单。从你来的地方。在registry.addMapping("/**");您可以添加您的客户端 URL,或者还有另一种称为反向代理的复杂解决方案。我假设这个项目很小。
  • 但我不是 API 的作者,我无法添加我的客户端。这就是为什么我问如何绕过它?
  • 服务器负责报告允许的来源。 Web 浏览器负责强制要求仅从允许的域发送请求。但是,这是可能的。您能分享一下您在客户端使用的 pl 吗?
【解决方案2】:

哦,你有一个完全不同的问题。你的代码还不错。

阅读本帖https://github.com/simonprickett/allthepokemon/issues/1

为此,请将您的端点更改为http://pokeapi.salestock.net/api/v2/

如果这也无济于事,请使用https://cors.now.sh/https://your_URL

https://cors.now.sh 启用反向代理,绝对 URL 肯定可以工作。

这是一个相当奇怪的解决方案,但它就是这样。

【讨论】:

    【解决方案3】:
    import java.io.IOException;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    
    @Component
    
    public class SimpleCORSFilter implements Filter {
    
    private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);
    
    public SimpleCORSFilter() {
        log.info("SimpleCORSFilter init");
    }
    
    @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", request.getHeader("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", "Content-Type, Accept, X-Requested-With, remember-me");
    
        chain.doFilter(req, res);
    }
    
    @Override
    public void init(FilterConfig filterConfig) {
    }
    
    @Override
    public void destroy() {
    }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2021-11-04
      • 1970-01-01
      • 2017-09-05
      • 2019-09-24
      • 2019-12-14
      • 2019-06-30
      • 2021-10-31
      • 2017-05-28
      • 2017-08-31
      相关资源
      最近更新 更多