网站维护费一年多少钱,长春网站上排名,平泉网站建设,微信网站链接怎么做背景#xff1a;前端在抖音里做了一个插件然后访问我们的后端。显然在抖音访问其他域名肯定会跨域。
解决办法#xff1a;
1、使用比较简单的jsonp
JSONP
优点#xff1a;JSONP 是通过动态创建 script 标签的方式加载外部数据#xff0c;属于跨域数据请求的一种…背景前端在抖音里做了一个插件然后访问我们的后端。显然在抖音访问其他域名肯定会跨域。
解决办法
1、使用比较简单的jsonp
JSONP
优点JSONP 是通过动态创建 script 标签的方式加载外部数据属于跨域数据请求的一种传统解决方案。JSONP 不会受到浏览器的同源策略限制因此在某些跨域环境如抖音小程序中可以正常工作。
缺点只能进行 GET 请求无法支持 POST、PUT 等其他 HTTP 方法。
安全性较低因为 JSONP 将代码直接注入到页面中存在潜在的安全风险。
测试案例
后端 springboot
RestController
Slf4j
RequestMapping(/api)
public class CrosController {GetMapping(/author/info)public String crosTest(RequestParam(authorName) String authorName,RequestParam(value callback, required false) String callback){// 参数校验if (authorName null) {return Invalid request: authorName is required;}// 模拟返回数据String jsonData {\author_id\: 12345, \author_name\: \ authorName \};// 判断是否为 JSONP 请求if (callback ! null !callback.isEmpty()) {// JSONP 响应String jsonpResponse callback ( jsonData );;return jsonpResponse;} else {// 普通 JSON 响应return jsonData;}}}前端html页面
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/title
/headbody/body/htmlscriptfunction jsonpRequest(url, params, callbackName) {return new Promise((resolve, reject) {// 动态创建回调函数名称const uniqueCallback callbackName || jsonpCallback_${Date.now()};// 将回调函数注册到全局对象中window[uniqueCallback] function (response) {// 清理全局回调函数和 script 标签delete window[uniqueCallback];document.body.removeChild(script);// 返回响应数据resolve(response);};// 构建完整的 URL拼接参数const query Object.entries(params).map(([key, value]) ${key}${encodeURIComponent(value)}).join();const fullUrl ${url}?${query}callback${uniqueCallback};// 创建 script 标签const script document.createElement(script);script.src fullUrl;// 处理加载失败script.onerror function () {delete window[uniqueCallback];document.body.removeChild(script);reject(new Error(JSONP request failed));};// 插入 script 标签到文档中document.body.appendChild(script);});
}// 使用示例
const url http://localhost:8080/api/author/info;
const params { authorName: 烟火中的水滴 };jsonpRequest(url, params).then((data) {console.log(Author Info:, data);}).catch((error) {console.error(Error:, error);});/script然后打开次页面。 1、打开控制台 2、执行 可以看到结果正常返回了
jsonpRequest(url, params).then((data) {console.log(Author Info:, data);}).catch((error) {console.error(Error:, error);});2、CrossOrigin 解决跨域
Spring Boot 的 CrossOrigin 注解用于配置 CORS跨域资源共享它允许你的后端接受来自其他域的请求。
优点CORS 是更现代、更安全的跨域解决方案相比 JSONP支持所有 HTTP 方法如 GET、POST 等。安全性高因为 CORS 会进行严格的域名、方法等验证。 缺点如果客户端如抖音小程序对 CORS 的处理有限可能无法支持复杂的预检请求如 OPTIONS 请求。CORS 依赖浏览器的支持如果环境对跨域限制较为严格如一些小程序环境可能 CORS 不生效。 我们先开启后端运行起来。看一些问题
1、通过控制台源null模拟跨域
后端代码
RestController
Slf4j
RequestMapping(/api)
public class CrosController {GetMapping(/author/info/cross)public String crossTest(RequestParam(authorName) String authorName){// 参数校验if (authorName null) {return Invalid request: authorName is required;}// 模拟返回数据String jsonData {\author_id\: 12345, \author_name\: \ authorName \};return jsonData;}}1、通过curl 请求 curl http://localhost:8080/api/author/info/cross?authorName123 结果 {author_id: 12345, author_name: 123} 这个属于正常的 2、打开一个index.html 然后控制台通过 前端代码访问这个接口
fetch(http://localhost:8080/api/author/info?authorName烟火中的水滴).then(response response.json()).then(data console.log(JSON Response:, data)).catch(error console.error(Error:, error));发现报错 问题分析 错误提示 No ‘Access-Control-Allow-Origin’ header is present on the requested resource 表示目标服务器http://localhost:8080没有返回允许跨域访问的CORS响应头。 浏览器的安全机制会拦截请求响应。 根本原因 客户端代码运行的index.html被浏览器认为是从null源加载的例如直接从文件系统打开与http://localhost:8080是不同源。 目标服务器未配置CORS。 其实这个就是跨域了因为你从一个控制台打开访问8080端口 但是你不是同源的就会报错。 那么解决办法就是加一个注解 CrossOrigin(origins *) // 允许指定来源跨域GetMapping(/author/info/cross)public String crossTest(RequestParam(authorName) String authorName){// 参数校验if (authorName null) {return Invalid request: authorName is required;}// 模拟返回数据String jsonData {\author_id\: 12345, \author_name\: \ authorName \};return jsonData;}重新访问 fetch(http://localhost:8080/api/author/info/cross?authorName烟火中的水滴) .then(response response.json()) .then(data console.log(JSON Response:, data)) .catch(error console.error(Error:, error)) 成功了 我们看下他发起的curl请求参数
curl http://localhost:8080/api/author/info/cross?authorName%E7%83%9F%E7%81%AB%E4%B8%AD%E7%9A%84%E6%B0%B4%E6%BB%B4 \-H Accept: */* \-H Accept-Language: zh-CN,zh;q0.9 \-H Connection: keep-alive \-H Origin: null \-H Sec-Fetch-Dest: empty \-H Sec-Fetch-Mode: cors \-H Sec-Fetch-Site: cross-site \-H User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 \-H sec-ch-ua: Chromium;v130, Google Chrome;v130, Not?A_Brand;v99 \-H sec-ch-ua-mobile: ?0 \-H sec-ch-ua-platform: macOS源是null实际也属于跨域的。 上面是的源是null 我们接下来用python模拟一个源请求 模拟跨域就得开启一个前端服务器 然后请求后端。
2、模拟前端服务器 端口3000实现跨域
使用 Python自带启动 HTTP 服务器 在终端中进入你的 index.html 所在的目录并运行以下命令 python -m http.server 3000
这会在 localhost:3000 上启动一个 HTTP 服务器。然后在浏览器中访问 然后打开浏览器 访问 http://localhost:3000/index.html 打开控制台执行 fetch(http://localhost:8080/api/author/info/cross?authorName烟火中的水滴) .then(response response.json()) .then(data console.log(JSON Response:, data)) .catch(error console.error(Error:, error)) 最后我们打开Network看下他发起的请求是不是真的跨域了。 通过查看curl命令确实跨域了
curl http://localhost:8080/api/author/info/cross?authorName%E7%83%9F%E7%81%AB%E4%B8%AD%E7%9A%84%E6%B0%B4%E6%BB%B4 \-H Accept: */* \-H Accept-Language: zh-CN,zh;q0.9 \-H Connection: keep-alive \-H Origin: http://localhost:3000 \-H Referer: http://localhost:3000/ \-H Sec-Fetch-Dest: empty \-H Sec-Fetch-Mode: cors \-H Sec-Fetch-Site: same-site \-H User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 \-H sec-ch-ua: Chromium;v130, Google Chrome;v130, Not?A_Brand;v99 \-H sec-ch-ua-mobile: ?0 \-H sec-ch-ua-platform: macOS