前后端分离项目跨域问题,浏览器控制台报错:No 'Access-Control-Allow-Origin' header is present on the requested resource.
请求方法为OPTIONS,状态值为302或403。
我的JS请求代码如下:
function doPost() {
let params = {
userName:"朱",
pwd : "bestv001",
birthday : "2022-12-06"
};
const xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", "http://localhost:8180/demo_war_exploded/login2?accessToken=dfgddf");
xmlHttp.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
xmlHttp.send(JSON.stringify(params));
xmlHttp.onreadystatechange = function () {
// 为了保证 数据 完整返回,我们一般会判断 两个值
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
//(5)服务端相应:如果能够进入这个判断,说明数据请求成功了
console.log('数据返回成功:' + JSON.stringify(xmlHttp.responseText));
alert(JSON.stringify(xmlHttp.responseText))
}
};
}
是 POST 请求,且 Content-Type = 'application/json; charset=utf-8'
,其实Content-Type
字段的类型为application/json
的 POST 请求,CORS
规定,Content-Type
不属于以下类型的,都属于预检请求 (preflight
request):
application/x-www-form-urlencoded
multipart/form-data
text/plain
发送"预检请求"时,需要用到方法 OPTIONS
。
服务端的代码很简单,如下:
@PostMapping(value = "/login2")
@ResponseBody
public LoginReq login2(@RequestBody LoginReq req, HttpServletRequest servletRequest, HttpServletResponse response) {
System.out.println("---- login2 ----- userName = " + req.getUserName());
// // 设置js请求跨域解决
// response.setHeader("Access-Control-Allow-Origin", "*");
// response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
String accessToken = servletRequest.getParameter("accessToken");
System.out.println("---- login2 --------------- accessToken = " + accessToken);
String user = JSONObject.toJSONString(req);
System.out.println("---- login2 ----- user = " + user);
System.out.println("---- login2 ----- birthday = " + req.getBirthday());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date date = null;
try {
date = simpleDateFormat.parse(simpleDateFormat.format(req.getBirthday()));
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("date = " + simpleDateFormat.format(date));
req.setBirthday(new Date());
if (req.getUserName().isEmpty() || req.getPwd().isEmpty()) {
throw new RuntimeException("userName or pwd is empty");
}
return req;
}
修改本地服务端项目中的 web.xml 文件,如下图:
如果项目中有其他的 filter
,那么把即将添加的跨域 filter
放在其他 filter
的前面,如下:
<filter>
<filter-name>MyCorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>http://localhost:63342</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>18</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyCorsFilter</filter-name>
<url-pattern>/*
其中 http://localhost:63342
就是我的网页地址,改成你自己的地址就好,重启 Tomcat ,再次运行就 OK了。