V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fstar
V2EX  ›  程序员

浏览器跨域请求,为什么简单请求直接就发送了,非简单请求还要先发一个 options 方法的预检请求?

  •  
  •   fstar · 105 天前 · 2327 次点击
    这是一个创建于 105 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我觉得这是不是设计有问题。

    如果我来设计的话,不分什么简单不简单请求,全都先发一个 options 。或者全都直接直接发原请求。

    这样不上不下的设计真的很奇怪啊。

    23 条回复    2022-04-26 19:49:48 +08:00
    vance123
        1
    vance123  
       105 天前
    为了前向兼容,前端里很多奇奇怪怪的地方都是有历史原因的
    sujin190
        2
    sujin190  
       105 天前 via Android
    get 单独发浪费性能增加延迟吧,post 之类的直接发不泄露数据了吧,那你这跨域限制不废了么,这又不复杂的优化有啥难理解的
    lscho
        3
    lscho  
       105 天前
    按你的理论,直接取消跨域就完事了。
    wwqgtxx
        4
    wwqgtxx  
       105 天前
    总有人觉得自己能在十几年前预判现在的发展
    noe132
        5
    noe132  
       105 天前
    简单来说因为历史原因。
    statumer
        6
    statumer  
       105 天前 via iPhone
    照理说 jsonp 这个东西也是不应该存在的,都是历史包袱
    Chism
        7
    Chism  
       105 天前 via Android
    @sujin190
    跨域请求 post 是先发个 get 试探,可以了再 post 吗?
    honkew
        8
    honkew  
       105 天前
    需要拿到响应头,才能知道允不允许跨域啊
    yin1999
        9
    yin1999  
       105 天前 via Android
    @Chism 用的是 option 请求,而非 get
    ch2
        10
    ch2  
       105 天前   ❤️ 3
    因为浏览器加载 js 跟 html 、css 、jpg 这些静态文件默认都是 GET ,一个网站在打开的一瞬会大量加载这些文件。往往加载这些文件的时候不会携带 cookie 等机密数据,所以就不预先 option 了,完全没必要。但是 fetch 、xhr 、ajax 等发送请求往往是带 cookie 的,这时候又不好单独鉴别是不是 fetch 跟 xhr 、ajax 发的 GET 请求,所以就只给 POST 预检 option ,不管 GET 了
    ch2
        11
    ch2  
       105 天前
    @ch2 #10 跨域主要是防止你的网站盗用别人网站的凭据刷 api ,这样至少可以保证别人盗用你网站 cookie 的 POST 发都发不出去
    Puteulanus
        12
    Puteulanus  
       105 天前   ❤️ 1
    简单请求可以走其他方式发,比如 get 用图片的 src ,post 构造个表单直接 submit ,为了向上兼容不能拦这些,单独拦截异步请求发送的跨域请求就没有意义了
    复杂请求因为无法用这种手段构造,所以拦截跨域是有意义的,但是全拦了大家又不方便,所以改用 option 询问一下服务器该不该拦
    mxT52CRuqR6o5
        13
    mxT52CRuqR6o5  
       105 天前 via Android
    因为有些接口有副作用,就比如转账接口,按照你的设计,虽然没有获取到转账结果,但转账请求发出去了
    tyx1703
        14
    tyx1703  
       105 天前 via iPhone
    可能是因为简单请求的 http 报文小,发过去就算被拒绝了代价也比较小。非简单请求往往报文比较大,发过去再拒绝会造成资源浪费。而增加 options 预检,无论从时间还是空间维度,未增加过大负担,但带来的好处却显而易见。
    lisongeee
        15
    lisongeee  
       105 天前
    @ch2

    “跨域主要是防止你的网站盗用别人网站的凭据刷 api ,这样至少可以保证别人盗用你网站 cookie 的 POST 发都发不出去”

    跨域中 简单请求 不需要预检,可以直接发出去,但是不一定收回来
    DOLLOR
        16
    DOLLOR  
       105 天前
    所以,干脆所有接口都用 post+json ,不用纠结什么“简单请求”,就没那么多事了🐶
    weixiangzhe
        17
    weixiangzhe  
       104 天前
    现在 chrome 是 有一次 option 成功,之后就没有 option 了吧
    lalalaqwer
        18
    lalalaqwer  
       104 天前
    @weixiangzhe 服务端可以通过 http 头控制 option 的作用时间的
    fstar
        19
    fstar  
    OP
       104 天前
    @weixiangzhe 哦,这个是缓存。`Access-Control-Max-Age: 86400` 可以设置缓存时间。
    bertonzh
        20
    bertonzh  
       104 天前
    是有一些设计问题,比如 request 的 content-type 为 application/json 需要发预检,而 www-form-urlencoded 却不需要。明明这两种只是序列化的方式不同而已。
    另外如果自定义了 header ,也要发预检,这个也挺奇怪的。

    要我设计,就应该 GET 都不发,POST PUT 等都发。
    ssshooter
        21
    ssshooter  
       104 天前
    get 是因为不改变服务器数据才让直接发的,post 发的有可能服务器已经处理完了(只是返回结果被浏览器拦截了),为了防止服务器被跨域修改数据才让 post 等方法先发 options 吧
    weixiangzhe
        22
    weixiangzhe  
       104 天前
    @fstar 这样的吗,学习了
    lewinlan
        23
    lewinlan  
       104 天前 via Android
    后端可以拦截 get
    前端只是尽力
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4344 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 65ms · UTC 01:46 · PVG 09:46 · LAX 18:46 · JFK 21:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.