请求头没有origin参数_跨域请求异常解决

3475df542c272c8524073e7903b21731.png

项目需要,使用前端直接调用服务端开放接口(本应该是服务端调用),由于域名不同,需要解决跨域名问题。

常见的跨域解决方案:https://segmentfault.com/a/1190000011145364

通过jsonp跨域

• document.domain + iframe跨域

• location.hash + iframe跨域

•window.name + iframe跨域

•postMessage跨域

•跨域资源共享(CORS)

•Access-Control-Allow-Origin

•Nodejs中间件代理跨域

•WebSocket协议跨域

本方案临时采用:Access-Control-Allow-Origin配置方案,在nginx配置了允许跨域访问:

add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';

偶尔还是会出现跨域请求失败提示,不是必现,拿到请求代码后模拟,必现了:

        Title    发送请求    $(function(){        $('#send').click(function () {            var postData ={ "actions":[ {"deviceIdentifier":"A010205-12335", "functionIdentifier":"预置位调用","inputs":{"摄像机Id":"8","预置位编号":"1"}}],"controlNo": "123456543","userId": "21"};            $.ajax({                type: "POST",                url: "http://61.155.**.**:38080/api/device/twin/device-service/sync",                contentType: 'application/json',                data:postData,                dataType: "json",                success:function (message) {                    alert("提交成功"+JSON.stringify(message));                },                error:function (message) {                    alert("提交失败"+JSON.stringify(message));                }            });        });    });

提交失败:error:{"readyState":0,"responseText":"","status":0,"statusText":"error"}

使用postman调用,返回正常:

01551c1efa3f53b8e2943524f1d186e4.png

浏览器应该不会弄错,提示跨域肯定是响应头没有返回 Access-Control-Allow-Origin' '*',抓包发现,果然响应头没有这个信息,但一看响应体内容是:

{    "code": "internal.server.error",    "message": "【系统异常】\norg.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('1' (code 49)): was expecting comma to separate Object entries; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('1' (code 49)): was expecting comma to separate Object entries\n at [Source: (PushbackInputStream); line: 5, column: 34] (through reference chain: com.isyscore.os.twin.run.model.dto.ControlServiceDTO[\"actions\"]->java.util.ArrayList[0])",    "detail": "org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('1' (code 49)): was expecting comma to separate Object entries; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('1' (code 49)): was expecting comma to separate Object entries\n at [Source: (PushbackInputStream); line: 5, column: 34] (through reference chain: com.isyscore.os.twin.run.model.dto.ControlServiceDTO[\"actions\"]-...}

OK,这里明白了,由于提交的数据不正常非标准json,导致服务端异常,500,没有正常返回Access-Control-Allow-Origin' '*', 即nginx配置的响应头,没有包含500这种异常返回。

网上一搜,也有网友遇到:https://www.dazhuanlan.com/2019/11/23/5dd9465a6643c/


原因和解决办法

原因其实很简单,是因为在 nginx 转发 server 响应的过程中, add_header 只有在 200, 201, 204, 206, 301, 302, 303, 304, 307 状态码时会添加,而 401, 500 都没有添加。

解决:看上面的配置,在 add_header 最后加上 always,可以让 nginx 在非 200, 300 的状态码后面,也使得 add_header 生效。

完整的nginx配置:

add_header 'Access-Control-Allow-Origin' '*' always;add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range' always;add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range' always;
如果您在跨域请求中无法接收到参数,可能是由于跨域请求的限制导致的。为了解决这个问题,您可以尝试以下方法: 1. 使用CORS(跨域资源共享):在后端服务器上配置允许跨域请求。在响应头中添加`Access-Control-Allow-Origin`字段,并设置为允许访问的域名。例如,在后端代码中添加以下代码: ```java response.setHeader("Access-Control-Allow-Origin", "http://example.com"); ``` 这将允许来自`http://example.com`域名的请求访问您的后端接口。您可以根据需要设置允许访问的域名或使用通配符`*`允许所有域名进行访问。 2. 使用代理:如果无法在后端进行配置或者对所有请求开放跨域访问,您可以考虑使用代理来解决跨域问题。在您的前端代码中,将跨域请求发送给同一域下的代理服务器,然后由代理服务器将请求转发到后端服务器。这样,您的前端代码就可以避免跨域请求的限制。 3. JSONP:如果您无法修改后端服务器的配置,并且后端支持返回JSONP格式的数据,您可以尝试使用JSONP来解决跨域问题。JSONP通过在前端动态创建`<script>`标签来加载远程脚本,从而绕过浏览器的跨域限制。请注意,JSONP只支持GET请求,并且需要后端服务器提供支持。 请根据您的具体情况选择适合的解决方案。希望以上建议对您有所帮助!如果您有任何进一步的问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值