英文:
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():
# ... 函数的其他部分 ...
输出结果是正常的。
有以下问题:
- 如何在 Jersey Java 中实现 CORS(类似于 Flask+Python)?
- 请为这个问题提供解决方案。
英文:
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
{
"firstName":"David",
"lastName":"Parker",
"school":"CSI",
"standard":"4",
"rollNumber":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'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", "*");
}
}
Also, I have added the following in 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>
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['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
The output is perfect
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'}
Questions:
- How to achieve CORS in Jersey Java (similar to Flask+Python)?
- Please provide a solution for this issue
答案1
得分: 1
解决方案已找到
基于视频:
在JAX-RS项目中启用CORS
https://www.youtube.com/watch?v=CDEeOWKza2Q
步骤如下:
右键单击任何包 > 新建 > 过滤器
Java包 > com.logicbig.example
类名 > CorsFilter > 下一步
双击 /CorsFilter > 模式 > /rest/* > 确定 > 下一步
确保 > 接口 = javax.servlet.Filter > 完成
观察到新的类(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 > com.logicbig.example
Class Name > CorsFilter > Next
Double click /CorsFilter > Pattern > /rest/* > Ok > Next
Ensure > Interface = javax.servlet.Filter > 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("Access-Control-Allow-Origin", "http://localhost:3000");
resp.addHeader("Access-Control-Allow-Headers", "*");
resp.addHeader("Access-Control-Allow-Methods", "*");
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论