获取游戏链接

小游戏是通过iframe嵌入到页面中的,之前抓取iframe的链接,直接在新标签页打开,是能看到一个纯纯的小游戏,但现在策略改了,直接打开iframe中小游戏的链接,会提示“请从4399域名访问”
观察该url的网络请求,会有一个Referer,也正是因为这个Referer才导致不能从其他页面引用该小游戏的iframe链接
image.png
要想在localhost的测试地址成正确嵌入iframe而不报错,也验证是不是因为Referer的原因,可以把本地host做一个映射:
127.0.0.1 www.4399.com
结果能正确访问,也验证了确实限制了Referer,但不可能把自己的域名配置成4399.com,所以还是要想办法绕过限制

绕过Referer的限制

  1. 前端处理:前端没有办法仿造referer
  2. 后端转发:在后端就可以通过http请求拿到链接内容时,指定referer ```javascript import axios from ‘axios’; import { getUrlParam } from ‘../helpers/utils’;

export default async function (req, res) { res.setHeader(‘Content-Type’, ‘text/html; charset=utf-8’); const param = getUrlParam(req.url); const url = param && param.url; const config = { headers: { Referer: ‘http://www.4399.com‘ } }; const data = await axios.get(decodeURIComponent(url), config); res.end(data); }

  1. 调用:
  2. ```javascript
  3. <iframe
  4. frameborder="0"
  5. scrolling="no"
  6. allowfullscreen="allowfullscreen"
  7. referrerpolicy="same-origin"
  8. :src="`/tapi/xyx/iframe?url=${encodeURIComponent(http://sda.4399.com/4399swf/upload_swf/ftp24/gamehwq/20180316/15b/index.htm)}`"
  9. class="url_container"
  10. style="width: 714px; height: 535px;"
  11. />

处理静态资源访问

通过后端代理以后,代码中想多路径都变成相对于/tapi/xyx/iframe的路径了,这显然不是我们想要的,应该是相对于小游戏部署的路径,这里就是http://sda.4399.com/4399swf/upload_swf/ftp24/gamehwq/20180316/15b 。解决这个问题可以通过设置base,将base标签插入到代码head中:

  1. const data = await axios.get(decodeURIComponent(url), config);
  2. const str = data.data
  3. .replace('<head>', '<head><base href="http://sda.4399.com/4399swf/upload_swf/ftp24/gamehwq/20180316/15b/" />');
  4. res.end(str);

这样相对路径的静态资源就能访问到了了。

document.location.href处理

代码中有使用document.location.href的地方,因为做了转发,所以这个值也变了,所以对返回结果中出现这个值的地方做硬编码替换

  1. const data = await axios.get(decodeURIComponent(url), config);
  2. const str = data.data
  3. .replace('<head>', '<head><base href="http://sda.4399.com/4399swf/upload_swf/ftp24/gamehwq/20180316/15b/" />')
  4. .replace('document.location.href', '\'http://sda.4399.com/4399swf/upload_swf/ftp24/gamehwq/20180316/15b/index.htm\'');
  5. res.end(str);

JS引入的动态生成

返回的html中,JS文件的引入不是直接写的script标签,而是通过createElement生成的,这样生成的代码就不允许JS跨域了,否则浏览器会报CROS错误

  1. (function (document, url, fgJS, firstJS) {
  2. fgJS = document.createElement('script');
  3. firstJS = document.getElementsByTagName('script')[0];
  4. fgJS.src = url + encodeURIComponent(document.location.href);
  5. firstJS.parentNode.insertBefore(fgJS, firstJS);
  6. })(document, './gameapi/v1.js?e=');

遇到跨域问题,基本上就无解了,gameapi/v1.js里面的js引用依然是通过createElement生成的

结论

外部网站直接嵌入小游戏不可行