V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
ChatGPTPRO
V2EX  ›  程序员

请教前端大佬:一个很蛇皮的跨域问题

  •  
  •   ChatGPTPRO · 2023-10-10 10:42:42 +08:00 · 4060 次点击
    这是一个创建于 442 天前的主题,其中的信息可能已经有所发展或是发生改变。

    打开这个地址: https://api.likepoems.com/img/bing/

    它会自动跳转到一个图片的地址,然后可以看到浏览器 url 变化了。

    我想在代码中先 axios 请求这个地址,获取到真实的图片地址以及 base64 ,但是它报跨域了。这个地址是网上公共的,所以走允许跨域是走不通。

    在代码中直接用 window.open("https://api.likepoems.com/img/bing/") 这个方式是可以成功打开这个地址且显示图片的。

    我也想过用浏览器父子窗口通信的方式来获取上述需要的信息,但是也没解决。

    41 条回复    2023-10-12 04:29:18 +08:00
    ChatGPTPRO
        2
    ChatGPTPRO  
    OP
       2023-10-10 10:53:47 +08:00
    @MrYELiex 阿这阿这
    7inFen
        3
    7inFen  
       2023-10-10 10:55:17 +08:00
    前端没法处理,postMessage 也是需要源网站配合才可以
    liuhuihao
        4
    liuhuihao  
       2023-10-10 10:56:46 +08:00
    源站不是你的不配合的话,无解。考虑非前端的方式吧,比如提前在后台把 重定向的地址跑出来然后返回给前端
    ChatGPTPRO
        5
    ChatGPTPRO  
    OP
       2023-10-10 11:03:42 +08:00
    @liuhuihao

    其实这个图片可以显示出来,那是不是意味着 html 里面就加载了,那是不是 base64 是能拿到的呢。至少说这个图片数据

    @7inFen
    xiaohundun
        6
    xiaohundun  
       2023-10-10 11:06:39 +08:00
    你用的人家的 API 不是已经提供了一个获取图片信息的接口了么,里面有 url
    xiaohundun
        7
    xiaohundun  
       2023-10-10 11:07:07 +08:00
    liuhuihao
        8
    liuhuihao  
       2023-10-10 11:09:00 +08:00
    @ChatGPTPRO #5 你最终目的是什么呢?
    如果说只是想要在你的页面里嵌入人家的这张图片,iframe 就可以实现正如你所说的可以正常显示。但是你想拿到图片的 base64 啥的在我了解的范围内前端是没法实现的,只能后台实现
    liuhuihao
        9
    liuhuihao  
       2023-10-10 11:11:42 +08:00
    @liuhuihao #8 除非对方接触跨域的限制或者提供不限制跨域的接口
    7inFen
        10
    7inFen  
       2023-10-10 11:13:34 +08:00
    @ChatGPTPRO 图片显示是渲染引擎 WebKit 的工作,不存在跨域;操作 base64 是 js 引擎 V8 的工作,有跨域限制。
    weixiangzhe
        11
    weixiangzhe  
       2023-10-10 11:13:37 +08:00
    做个反代吧
    ChatGPTPRO
        12
    ChatGPTPRO  
    OP
       2023-10-10 11:15:27 +08:00
    @xiaohundun 大佬你咋这么强啊
    xiaohundun
        13
    xiaohundun  
       2023-10-10 11:18:28 +08:00
    @ChatGPTPRO #12 😰可能你没看 API 主的网站吧,这接口应该还允许跨域,我没试
    676529483
        14
    676529483  
       2023-10-10 11:18:53 +08:00
    如果只是显示图片,img 标签不需要跨域
    gogogo2000
        15
    gogogo2000  
       2023-10-10 11:19:14 +08:00
    @ChatGPTPRO #5 对浏览器来说确实是获得到了,但是浏览器会限制非同域的脚本,不允许你获得图片的任何信息
    ChatGPTPRO
        16
    ChatGPTPRO  
    OP
       2023-10-10 11:22:13 +08:00
    @xiaohundun 大佬,确实可以得到真实的图片地址。

    ```
    {
    "code": 200,
    "url": "https://jihulab.com/weblog/gallery02/-/raw/master/BingImage/2021-06-16/OHR.GBRTurtle_ZH-CN6069093254_UHD.jpg",
    "width": 5164,
    "height": 2905,
    "size": "2386539",
    "mime": "image/jpeg"
    }
    ```

    但是有个问题,怎么获取这个图片的 base64 呀
    xiaohundun
        17
    xiaohundun  
       2023-10-10 11:29:43 +08:00
    @ChatGPTPRO #16 4 楼给你解释过了,虽然 img 可以渲染但是你要请求图片还是会碰到跨域问题,所以后端
    xiaohundun
        18
    xiaohundun  
       2023-10-10 11:33:07 +08:00
    @ChatGPTPRO #16 你试下这个,https://stackoverflow.com/questions/46609800/canvas-crossorigin-anonymous-cors-chrile-mac-osx ,说是吧 img 绘制成 canvas 然后再转
    mxT52CRuqR6o5
        19
    mxT52CRuqR6o5  
       2023-10-10 11:35:10 +08:00
    跨域图片(如果没加允许跨域的那些 headers ),没做防盗链的话,你可以用 img 加载展示,但你无法获取具体的数据( ajax 、fetch )
    你想把这个 img 画到 canvas 上都是做不到的
    之前甚至有人研究旁路攻击去偷跨域图片内容的操作( https://www.secrss.com/articles/3102 ,能偷的不止有图片)
    mxT52CRuqR6o5
        20
    mxT52CRuqR6o5  
       2023-10-10 11:38:28 +08:00
    @mxT52CRuqR6o5 #19
    又回忆了一下,「画到 canvas 上都是做不到的」说的有问题,不是做不到,而是如果把跨域 img 画到 canvas 上,就没法再对这个 canvas 执行 toBlob 、toDataUrl 这种拿到 canvas 画的内容的操作了
    liuhuihao
        21
    liuhuihao  
       2023-10-10 11:39:16 +08:00
    @xiaohundun #18 这个操作应该也是不行的,接口虽然允许跨域,但是这个图片地址的请求没返回 Access-Control-Allow-Origin ,还是不允许跨域的。不允许跨域的图片只能用 img 渲染出来,canvas 也会有跨域问题,我的知识范围内也是不可行的。
    liuhuihao
        22
    liuhuihao  
       2023-10-10 11:40:29 +08:00
    @liuhuihao #21 canvas 能画出来但是跨域的不能调用 toDataUrl 我记得
    liuhuihao
        23
    liuhuihao  
       2023-10-10 11:43:16 +08:00
    @ChatGPTPRO #12 综上所述,自己后台整个 反代解千愁
    solobat
        24
    solobat  
       2023-10-10 11:46:42 +08:00
    实在不行就用 https://deno.dev/ 代理下解决
    liuhuihao
        25
    liuhuihao  
       2023-10-10 11:47:28 +08:00
    我突然间有个疑问,浏览器的同源策略本身是为了防 A 网站非法调用 B 网站的接口,例如 A 网站是个冒牌的银行网站,然后调用 真银行的接口获取用户名密码一类的。

    但是反代可以绕过同源策略,A 网站只需要在自己的后台搭一套反向代理去请求 B 网站,一样可以骚操作模拟别的网站哈,感觉 浏览器这个同源策略也是 防君子不防小人哈哈,没啥卵用?
    heishu
        26
    heishu  
       2023-10-10 11:49:28 +08:00   ❤️ 1
    恕我直言,在座的各位都是~~~~~大佬
    realJamespond
        27
    realJamespond  
       2023-10-10 11:50:31 +08:00
    用 nodejs 就行了
    pkoukk
        28
    pkoukk  
       2023-10-10 11:55:10 +08:00
    @liuhuihao #25
    同源策略是为了防止你在 A 站使用 B 站的 cookie,localstorage 这些信息。
    如果没有同源策略,那么假如用户在 A 站登录了,登录信息在 A 站的 cookie 里,那么你的 B 站就可以直接调 A 站的接口
    有了之后,你就算搭了一套反代,B 站想用 A 站的接口,也得让用户在 B 站里,用 A 站的账户密码登录一次,这玩意叫钓鱼网站
    7inFen
        29
    7inFen  
       2023-10-10 11:56:07 +08:00
    @liuhuihao 是可以的,所以要提防在陌生网站输入账号密码
    sunfkny
        30
    sunfkny  
       2023-10-10 11:56:27 +08:00
    这个极狐 GitLab 仓库 https://jihulab.com/weblog/gallery02 不能跨域可以换一个,原始仓库是 https://github.com/myseil/BingWallpaper , 直接移花接木到 github
    https://gist.github.com/sunfkny/9855f30e0e9eaaef7b81d67e0c860150
    clue
        31
    clue  
       2023-10-10 13:52:42 +08:00
    @liuhuihao #25 如果你在浏览器同源策略规则外访问到了跨域数据,那证明这个浏览器有安全漏洞

    你说的反向代理问题,浏览器在请求不同域时,cookie 等信息都是完全隔离的。在浏览器这里,站点 A 的请求,只会带上 A 这个域的信息,所以你服务端的代理没任何作用

    同源策略本身是定义于浏览器的,HTTP 协议上的 cors 也只是它的延伸,最终服务于浏览器
    DOLLOR
        32
    DOLLOR  
       2023-10-10 14:17:54 +08:00
    @liuhuihao
    “同源策略” 的本质是不同应用之间的数据隔离。你把每个网站都看成一个 APP ,各 APP 都只能访问自己的数据,不就显得很天经地义了吗?
    所谓 “防 A 网站非法调用 B 网站的接口”,不过是应用数据隔离的附带效果罢了。
    unco020511
        33
    unco020511  
       2023-10-10 14:42:56 +08:00
    @liuhuihao #25 你说的是「钓鱼网站」,用户本身是需要在「钓鱼网站」输入账号密码的.浏览器的同源策略是隔离不同 domain 下的 cookie 等信息的,防止另一个网站直接拿你的信息去做请求
    leonshaw
        34
    leonshaw  
       2023-10-10 14:50:56 +08:00
    @liuhuihao 除了前面几楼所说的防止 A 使用 B 域的浏览器存储,还有一种情形是 A 可能访问不到 B 。例如 B 是一个没有鉴权的内网服务,如果没有同源策略,在公网的 A 就可以利用用户浏览器作跳板访问到 B 的资源。
    zuotun
        35
    zuotun  
       2023-10-10 15:22:00 +08:00
    如果只是拿到 bing 壁纸的话, 还有一大堆类似的. 我自己也做了一个(不做存储) https://api.kazusa.cc/bing
    至于解决办法, 还是反代最简单.
    yangjirun
        36
    yangjirun  
       2023-10-10 15:49:46 +08:00
    nginx 代理吧。最简单。
    JaaaaackZheng
        37
    JaaaaackZheng  
       2023-10-10 17:22:10 +08:00
    你的目的只是想将图片转 base64 ?
    JaaaaackZheng
        38
    JaaaaackZheng  
       2023-10-10 17:22:55 +08:00
    https://juejin.cn/post/6844903961141444615 用 canvas 就可以了,canvas 设置跨域就能转。我之前的项目转过
    okakuyang
        39
    okakuyang  
       2023-10-10 17:41:30 +08:00 via iPhone
    @JaaaaackZheng 跨域的图片转出来是白色的,你最好确认一下你以前的代码哦
    lmw2616
        40
    lmw2616  
       2023-10-10 18:00:14 +08:00
    request({
    method: 'get',
    url: 'https://api.likepoems.com/img/bing/',
    responseType:'arraybuffer',
    success: (res) => {

    //图片流转 blob
    let imageType = res.header['content-type'];
    const blob = new Blob([res.data], { type: imageType })

    //blob 转 base64
    let oFileReader = new FileReader()
    oFileReader.onloadend = function (e) {
    //base64 字符串
    const base64 = e.target.result
    }
    oFileReader.readAsDataURL(blob)
    }
    })
    YuJianrong
        41
    YuJianrong  
       2023-10-12 04:29:18 +08:00
    @JaaaaackZheng 当你在一个 Canvas 里用 DrawImage 绘制一非同源又没有 CORS 的图片的时候,这个 Canvas 会处于“被污染”( tainted )状态了。处于“被污染”状态的 Canvas 这些调用将会抛错:
    * Context 上的 getImageData()
    * Canvas 上的 toBlob(), toDataURL() 和 captureStream()
    这样来防止比如 OP 这种想抓图片内容的做法。

    详情: https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image#security_and_tainted_canvases
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1159 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 18:28 · PVG 02:28 · LAX 10:28 · JFK 13:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.