CORS 策略已阻止从源“http://localhost:3000”访问“http://localhost:9900/jaxrs-post-example/rest/customers”获取

Posted

技术标签:

【中文标题】CORS 策略已阻止从源“http://localhost:3000”访问“http://localhost:9900/jaxrs-post-example/rest/customers”获取【英文标题】:Access to fetch at 'http://localhost:9900/jaxrs-post-example/rest/customers' from origin 'http://localhost:3000' has been blocked by CORS policy 【发布时间】:2020-12-27 01:53:49 【问题描述】:

我已经从https://www.logicbig.com/tutorials/java-ee-tutorial/jax-rs/post-example.html下载了 Jersey Java Rest Api 示例

当我使用“在服务器上运行”运行这个项目时,它正在接受来自 Postman 的以下 Rest api 命令并且工作正常:

GET http://localhost:9900/jaxrs-post-example/rest/customers

POST http://localhost:9900/jaxrs-post-example/rest/customers

  "firstName":"David",
  "lastName":"Parker",
  "school":"CSI",
  "standard":"4",
  "rollNumber":85

当我从 ReactJS 发送相同的命令时,服务器在 ReactJS 中显示以下错误。

CORS 策略已阻止从源“http://localhost:3000”获取“http://localhost:9900/jaxrs-post-example/rest/customers”的访问权限:对预检请求的响应没有“ t 通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。

为了解决这个问题,我在 RestServer.java 中添加了以下内容 (基于How to handle CORS using JAX-RS with Jersey)

@Provider
@PreMatching
public class CorsFilter implements ContainerRequestFilter, ContainerResponseFilter 

    /**
     * Method for ContainerRequestFilter.
     */
    @Override
    public void filter(ContainerRequestContext request) throws IOException 

        // If it's a preflight request, we abort the request with
        // a 200 status, and the CORS headers are added in the
        // response filter method below.
        if (isPreflightRequest(request)) 
            request.abortWith(Response.ok().build());
            return;
        
    

    /**
     * A preflight request is an OPTIONS request
     * with an Origin header.
     */
    private boolean isPreflightRequest(ContainerRequestContext request) 
        return request.getHeaderString("Origin") != null
                && request.getMethod().equalsIgnoreCase("OPTIONS");
    

    /**
     * Method for ContainerResponseFilter.
     */
    @Override
    public void filter(ContainerRequestContext request, ContainerResponseContext response)
            throws IOException 

        // if there is no Origin header, then it is not a
        // cross origin request. We don't do anything.
        if (request.getHeaderString("Origin") == null) 
            return;
        

        // If it is a preflight request, then we add all
        // the CORS headers here.
        if (isPreflightRequest(request)) 
            response.getHeaders().add("Access-Control-Allow-Credentials", "true");
            response.getHeaders().add("Access-Control-Allow-Methods",
                "GET, POST, PUT, DELETE, OPTIONS, HEAD");
            response.getHeaders().add("Access-Control-Allow-Headers",
                // Whatever other non-standard/safe headers (see list above) 
                // you want the client to be able to send to the server,
                // put it in this list. And remove the ones you don't want.
                "X-Requested-With, Authorization, " +
                "Accept-Version, Content-MD5, CSRF-Token, Content-Type");
        

        // Cross origin requests can be either simple requests
        // or preflight request. We need to add this header
        // to both type of requests. Only preflight requests
        // need the previously added headers.
        response.getHeaders().add("Access-Control-Allow-Origin", "*");
    

另外,我在 web.xml 中添加了以下内容

    <web-app>
  <display-name>JAX-RS Web Application</display-name>
  <servlet>
    <servlet-name>jersey-json-example-serlvet</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
        <param-value>com.javacodegeeks.rest.jersey.server.CORSFilter</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.javacodegeeks.rest.jersey.server</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>jersey-json-example-serlvet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
</web-app>

当我尝试使用 CORS 的 Flask+Python 时,来自 ReactJS 的命令运行良好。

ReactJS 变化: fetch('http://localhost:5000/jaxrs-post-example/rest/customers',

Flask+Python 代码:

app = Flask(__name__)
app.config['SECRET_KEY'] = 'xyz'
app.config['CORS_HEADERS'] = 'Content-Type'
#Allow specific origin
cors = CORS(app, resources=r"/jaxrs-post-example/*": "origins": ["http://localhost:3000"])

@app.route('/jaxrs-post-example/rest/customers', methods=['GET', 'POST'])
def getStudent():
    print("You are getting getStudent request")
    content = request.json
    id = content['id']
    name = content['name']
    address = content['address']
    phoneNumber = content['phoneNumber']
    print("id = ", id)
    print("name = ", name)
    print("address = ", address)
    print("phoneNumber = ", phoneNumber)
    json_object = JFY("result": "getStudent is called")
    print("json_results = ", json_object)
    print("response for getStudent = ", json_object.get_json())
    return json_object

输出很完美

127.0.0.1 - - [08/Sep/2020 21:00:40] "OPTIONS /jaxrs-post-example/rest/customers HTTP/1.1" 200 -
127.0.0.1 - - [08/Sep/2020 21:00:41] "POST /jaxrs-post-example/rest/customers HTTP/1.1" 200 -
You are getting getStudent request
id =  2152
name =  David
address =  12,new street
phoneNumber =  8765489011
json_results =  <Response 39 bytes [200 OK]>
response for getStudent =  'result': 'getStudent is called'

问题:

    Jersey Java中如何实现CORS(类似Flask+Python)? 请为此问题提供解决方案

【问题讨论】:

您注册过滤器错误。显示你的整个 web.xml 整个 web.xml 已更新 您使用的是 Jersey 1.x。您拥有的过滤器是 2.x 您的配置是正确的,但过滤器是错误的。您需要使用 1.x 过滤器。略有不同。您将在链接中看到一个示例。 >>您将在链接中看到一个示例。 – ???缺少任何链接? 你的链接....... 【参考方案1】:

找到解决办法

根据视频: 在 JAX-RS 项目中启用 CORS https://www.youtube.com/watch?v=CDEeOWKza2Q

步骤如下:

右键单击任何包>新建>过滤器

    Java package > com.logicbig.example

    Class Name > CorsFilter > Next

    Double click /CorsFilter > Pattern > /rest/* > Ok > Next

    Ensure > Interface = javax.servlet.Filter > Finish

观察新类(CorsFilter)被创建

删除构造函数

在doFilter下添加以下内容


public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
        HttpServletResponse resp = (HttpServletResponse) response;
        resp.addHeader("Access-Control-Allow-Origin", "http://localhost:3000");
        resp.addHeader("Access-Control-Allow-Headers", "*");
        resp.addHeader("Access-Control-Allow-Methods", "*");
        chain.doFilter(request, response);
    

构建路径 > 外部 jar > 添加 > C://Tomcat/lib/servlet-api.jar

观察:所有错误都被删除

重新启动Tomcat

在服务器上运行

观察:来自 ReactJS 的 CORS 错误被移除

【讨论】:

【参考方案2】:

您必须从您尝试访问的服务启用跨源资源共享。请查看相关链接here。这很好地解释了如何在 JAXRS 中使用 Jersey 实现它。

【讨论】:

如果您阅读该问题,您会看到 OP 知道这是一个 CORS 问题,并链接到您作为解决方案来源链接的同一帖子。然而它仍然对他们不起作用。 我的坏...没有读完整篇。我提到的链接实际上对我有用。

以上是关于CORS 策略已阻止从源“http://localhost:3000”访问“http://localhost:9900/jaxrs-post-example/rest/customers”获取的主要内容,如果未能解决你的问题,请参考以下文章

CORS 策略已阻止访问从源“http://localhost:3000”获取

CORS 策略已阻止从源“null”访问图像

CORS 策略已阻止从源 URL 访问 URL 的 XMLHttpRequest [重复]

CORS 策略已阻止从源访问“http://localhost...”处的 XMLHttpRequest:

CORS 策略已阻止从源“http://localhost:3001”访问“blahblahblah”获取

Javascript:CORS 策略已阻止从源“http ...”获取“https ..”的访问权限 [重复]