Access to fetch at 'http://localhost:9900/jaxrs-post-example/rest/customers' from origin 'http://localhost:3000' has been blocked by CORS policy

huangapple go评论129阅读模式
英文:

Access to fetch at 'http://localhost:9900/jaxrs-post-example/rest/customers' from origin 'http://localhost:3000' has been blocked by CORS policy

问题

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

当我使用 "Run on server" 运行这个项目时,它可以接受来自 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 中显示以下错误:

Access to fetch at 'http://localhost:9900/jaxrs-post-example/rest/customers' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

为了解决这个问题,我在 RestServer.java 中添加了以下内容
(基于 https://stackoverflow.com/questions/28065963/how-to-handle-cors-using-jax-rs-with-jersey):

@Provider
@PreMatching
public class CorsFilter implements ContainerRequestFilter, ContainerResponseFilter {
    // ... 代码 ...
}

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

<web-app>
    <!-- ... 其他配置 ... -->
    <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>
        <!-- ... 其他初始化参数 ... -->
    </servlet>
    <servlet-mapping>
        <servlet-name>jersey-json-example-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

当我尝试使用 Flask+Python 并启用 CORS 时,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'
# 允许特定的来源
cors = CORS(app, resources={r"/jaxrs-post-example/*": {"origins": ["http://localhost:3000"]}})

@app.route('/jaxrs-post-example/rest/customers', methods=['GET', 'POST'])
def getStudent():
    # ... 函数的其他部分 ...

输出结果是正常的。

有以下问题:

  1. 如何在 Jersey Java 中实现 CORS(类似于 Flask+Python)?
  2. 请为这个问题提供解决方案。
英文:

I have downloaded Jersey Java Rest Api example from https://www.logicbig.com/tutorials/java-ee-tutorial/jax-rs/post-example.html

When I run this project using 'Run on server', it is accepting the following Rest api commands from Postman and perfectly working fine:

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

POST http://localhost:9900/jaxrs-post-example/rest/customers
{
  &quot;firstName&quot;:&quot;David&quot;,
  &quot;lastName&quot;:&quot;Parker&quot;,
  &quot;school&quot;:&quot;CSI&quot;,
  &quot;standard&quot;:&quot;4&quot;,
  &quot;rollNumber&quot;:85
}

When I send same command from ReactJS, the server is showing the following error in ReactJS.

>Access to fetch at 'http://localhost:9900/jaxrs-post-example/rest/customers' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

To fix this issue, I have added the following in RestServer.java
(Based on https://stackoverflow.com/questions/28065963/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&#39;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(&quot;Origin&quot;) != null
                &amp;&amp; request.getMethod().equalsIgnoreCase(&quot;OPTIONS&quot;);
    }

    /**
     * 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&#39;t do anything.
        if (request.getHeaderString(&quot;Origin&quot;) == null) {
            return;
        }

        // If it is a preflight request, then we add all
        // the CORS headers here.
        if (isPreflightRequest(request)) {
            response.getHeaders().add(&quot;Access-Control-Allow-Credentials&quot;, &quot;true&quot;);
            response.getHeaders().add(&quot;Access-Control-Allow-Methods&quot;,
                &quot;GET, POST, PUT, DELETE, OPTIONS, HEAD&quot;);
            response.getHeaders().add(&quot;Access-Control-Allow-Headers&quot;,
                // 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&#39;t want.
                &quot;X-Requested-With, Authorization, &quot; +
                &quot;Accept-Version, Content-MD5, CSRF-Token, Content-Type&quot;);
        }

        // 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(&quot;Access-Control-Allow-Origin&quot;, &quot;*&quot;);
    }
}

Also, I have added the following in web.xml

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

When I tried Flask+Python with CORS, the command from ReactJS is perfectly working.

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

Flask+Python code:

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

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

The output is perfect

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

Questions:

  1. How to achieve CORS in Jersey Java (similar to Flask+Python)?
  2. Please provide a solution for this issue

答案1

得分: 1

解决方案已找到

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

步骤如下:

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

    Java包 &gt; com.logicbig.example

	类名 &gt; CorsFilter &gt; 下一步

	双击 /CorsFilter &gt; 模式 &gt; /rest/* &gt; 确定 &gt; 下一步

	确保 &gt; 接口 = javax.servlet.Filter &gt; 完成

观察到新的类(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错误已移除

英文:

Solution is found

Based on the video:
Enable CORS in a JAX-RS Project
https://www.youtube.com/watch?v=CDEeOWKza2Q

The steps are:

Right click any package > New > Filter

    Java package &gt; com.logicbig.example

	Class Name &gt; CorsFilter &gt; Next

	Double click /CorsFilter &gt; Pattern &gt; /rest/* &gt; Ok &gt; Next

	Ensure &gt; Interface = javax.servlet.Filter &gt; Finish

Observe new class(CorsFilter) is created

Remove constructor

Add the following under doFilter


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

Build path > External jar > Add > C://Tomcat/lib/servlet-api.jar

Observe: All errors are removed

Re-Start Tomcat

Run on server

Observe: CORS error from ReactJS is removed

答案2

得分: -2

你必须在你尝试访问的服务中启用跨域资源共享。请查看相关链接这里。这个链接非常详细地解释了如何在JAXRS和Jersey中实现这一目标。

英文:

You have to enable cross origin resource sharing from the service you are trying to access. please check the related link here. This very nicely explains how to achieve it in JAXRS with Jersey.

huangapple
  • 本文由 发表于 2020年9月9日 00:25:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/63797965.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定