日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ios 请求头设置token_HTTP中的OPTIONS请求

發布時間:2023/12/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ios 请求头设置token_HTTP中的OPTIONS请求 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

http請求之前已經接觸了很多,但是這個options請求我還是第一次,剛來到公司的時候進行調試,發現NetWork里,每個請求在發出之前都會先發送一個options請求,第二個才是正常的請求。先來看下MDN官方的解釋。

MDN

HTTP 的 OPTIONS 方法 用于獲取目的資源所支持的通信選項。客戶端可以對特定的 URL 使用 OPTIONS 方法,也可以對整站(通過將 URL 設置為“*”)使用該方法。

作用:

  • 檢測服務器所支持的請求方法
  • CORS 中的預檢請求(preflight request)
  • 出現原因

    在說OPTIONS請求出的原因之前,要先說下瀏覽器的同源策略和跨域資源共享 CORS

    同源策略

    如果兩個URL的協議(protocol)、端口(port)、主機(host),都相同,則稱這個URL為同源。以http://music.javaswing.cn/home/index.html為例子:

    URL結果原因
    http://music.javaswing.cn/static/other.html同源
    http://music.javaswng.cn/inner/start.html同源
    http://music.javaswing.cn:8000/other.html不同源端口不同
    https://music.javaswing.cn/inner/start.html不同源協議不同
    http://api.javaswing.cn/start.html不同源主機不同

    作用:同源策略的存在,主要是為用于限制文檔與它加載的腳本如何能與另一個資源進行交互,為重要的安全策略。

    比如:你本地http://localhost:3000的項目訪問http://localhost:8000的項目,就會出現:has been blocked by CORS policy

    Access?to?XMLHttpRequest?at?'http://localhost:3000/'?from?origin?'http://localhost:8080'?has?been?blocked?by?CORS?policy:?Response?to?preflight?request?doesn't?pass?access?control?check:?No?'Access-Control-Allow-Origin'?header?is?present?on?the?requested?resource.

    CORS

    跨域資源共享(CORS) 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 ?讓運行在一個 origin (domain) 上的Web應用被準許訪問來自不同源服務器上的指定的資源。當一個資源從與該資源本身所在的服務器不同的域、協議或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。

    簡單的來說:CORS就是兩種在不同的域、協議或端口(即不在同源中),服務之間能相互訪問。

    OPTIONS請求

    說完了同源策略和CORS,接下來說下OPTIONS請求。在CORS機制一個域名A要訪問域名B的服務,在一些特殊的復雜請求下(簡單請求并不會進行預請求),瀏覽器必須先使用OPTIONS請求進行一個預檢請求(preflight request)來獲取B服務是否允許跨域請求,服務進行確認之后,才會發起真正的HTTP請求。在預檢請求的返回中,服務器端也可以通知客戶端,是否需要攜帶身份憑證(包括 Cookies 和 HTTP 認證相關數據)。

    簡單請求

  • http方法是以下之一:
    • GET
    • HEAD
    • POST
  • HTTP的頭信息不超出以下幾種字段:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (需要注意額外的限制)
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width
  • Content-Type 的值僅限于下列三者之一:
    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded

    實例

    環境:node 10.x ?koa ? vue

    瀏覽器:火狐

    本地vue環境:localhost:8080

    本地koa地址:localhost:3000

  • 先把koa的后臺進行設置為允許CORS,這里我沒有使用中間件,是自己進行處理的。
  • //?cors跨域處理
    app.use(async?(ctx,?next)?=>?{
    ????//?允許來息所有域名的請求
    ????ctx.set('Access-Control-Allow-Origin',?'*')
    ????
    ????//?允許HTTP請求的方法
    ????ctx.set('Access-Control-Allow-Methods',?'OPTIONS,DELETE,GET,PUT,POST')
    ????
    ????//?表明服務器支持所有頭信息字段
    ????ctx.set('Access-Control-Allow-Headers',?'x-requested-with,?accept,?origin,?content-type,?token')
    ????
    ????//?Content-Type表示具體請求中的媒體類型信息
    ????ctx.set('Content-Type',?'application/json;charset=utf-8')
    ????
    ????await?next()
    })
    • vue層面簡單的GET請求
    export?function?getList?()?{
    ????return?axios({
    ????????url:?`//localhost:3000`,
    ????????method:?'get'
    ????})
    }

    結果如下圖:

    image

    從圖中可以看到結果為正常的請求,并沒有進行發出OPTIONS請求進行預檢測。

    • 修改vue中的請求頭部分,添加一個header.token字段:
    export?function?getList?()?{
    ????return?axios({
    ????????url:?`//localhost:3000`,
    ????????method:?'get',
    ????????headers:?{token:?'test'}
    ????})
    }

    這里的GET請求,在HEADE中設置了token字段,不屬于簡單請求。所以發出了OPTIONS請求。但是,如果你只設置了ctx的頭,你會發現,請求還是會報錯

    Access?to?XMLHttpRequest?at?'http://localhost:3000/'?from?origin?'http://localhost:8080'?has?been?blocked?by?CORS?policy:?Response?to?preflight?request?doesn't?pass?access?control?check:?It?does?not?have?HTTP?ok?status.
    image

    preflight request doesn't pass access control check。說明的很清楚,就是options請求沒有正確的響應。

    解決方法有兩種:

  • 給options請求設置正常的響應
  • router.options('/',?async?(ctx,?next)?=>?{
    ????console.log('options');
    ????ctx.body?=?''
    })
  • 使用@koa-router中的allowedMethods方法
  • app.use(router.allowedMethods())

    從源碼看allowedMethods

    Router.prototype.allowedMethods?=?function?(options)?{
    ??options?=?options?||?{};
    ??var?implemented?=?this.methods;

    ??return?function?allowedMethods(ctx,?next)?{
    ????return?next().then(function()?{
    ??????var?allowed?=?{};

    ??????if?(!ctx.status?||?ctx.status?===?404)?{
    ????????ctx.matched.forEach(function?(route)?{
    ??????????route.methods.forEach(function?(method)?{
    ????????????allowed[method]?=?method;
    ??????????});
    ????????});

    ????????var?allowedArr?=?Object.keys(allowed);

    ????????if?(!~implemented.indexOf(ctx.method))?{
    ??????????//?服務器不支持該方法的情況
    ??????????if?(options.throw)?{
    ????????????var?notImplementedThrowable;
    ????????????if?(typeof?options.notImplemented?===?'function')?{
    ??????????????notImplementedThrowable?=?options.notImplemented();
    ????????????}?else?{
    ??????????????notImplementedThrowable?=?new?HttpError.NotImplemented();
    ????????????}
    ????????????throw?notImplementedThrowable;
    ??????????}?else?{
    ????????????//?響應?501?Not?Implemented
    ????????????ctx.status?=?501;
    ????????????ctx.set('Allow',?allowedArr.join(',?'));
    ??????????}
    ????????}?else?if?(allowedArr.length)?{
    ??????????if?(ctx.method?===?'OPTIONS')?{
    ????????????//?獲取服務器對該路由路徑支持的方法集合
    ????????????ctx.status?=?200;
    ????????????ctx.body?=?'';
    ????????????ctx.set('Allow',?allowedArr.join(',?'));
    ??????????}?else?if?(!allowed[ctx.method])?{
    ????????????if?(options.throw)?{
    ??????????????var?notAllowedThrowable;
    ??????????????if?(typeof?options.methodNotAllowed?===?'function')?{
    ????????????????notAllowedThrowable?=?options.methodNotAllowed();
    ??????????????}?else?{
    ????????????????notAllowedThrowable?=?new?HttpError.MethodNotAllowed();
    ??????????????}
    ??????????????throw?notAllowedThrowable;
    ????????????}?else?{
    ??????????????//?響應?405?Method?Not?Allowed
    ??????????????ctx.status?=?405;
    ??????????????ctx.set('Allow',?allowedArr.join(',?'));
    ????????????}
    ??????????}
    ????????}
    ??????}
    ????});
    ??};
    };

    可以看到在這個方法里當請求方式為OPTIONS會進行正常的返回處理。

    設置這個方法之后,再進行請求:

    image
  • 使用curl命令進行請求
  • $?curl?-X?OPTIONS?http://localhost:3000/?-i
    HTTP/1.1?200?OK
    Access-Control-Allow-Origin:?*
    Access-Control-Allow-Methods:?OPTIONS,DELETE,GET,PUT,POST
    Access-Control-Allow-Headers:?x-requested-with,?accept,?origin,?content-type,?to
    ken
    Content-Type:?application/json;charset=utf-8
    Content-Length:?0
    Allow:?HEAD,?GET,?POST,?PUT
    Date:?Sat,?01?Aug?2020?11:14:53?GMT
    Connection:?keep-alive

    HTTP 響應首部字段解釋表:

    CORS請求相關的字段,都以Access-Control-開頭

    字段名語法作用
    Access-Control-Allow-OriginAccess-Control-Allow-Origin:或 *orgin指定允許訪問該資源的URL,設置為*則為任意
    Access-Control-Allow-MethodsAccess-Control-Allow-Methods:[,]*用于預檢測請求響應,告訴瀏覽器實際請求支持的方法
    Access-Control-Allow-HeadersAccess-Control-Allow-Headers:[,]*用于預檢測請求響應,告訴瀏覽器實際請求中允許攜帶的字段
    Access-Control-Max-AgeAccess-Control-Max-Age:指定瀏覽器preflight請求能被緩存多長時間,單位(秒)
    Access-Control-Allow-CredentialsAccess-Control-Allow-Credentials: true當瀏覽器的credentials設置為true時是否允許瀏覽器讀取response的內容。在XMLHttpRequest中設置withCredentials為true,且設置了該屬性,則會帶到身份Cookies。如果Access-Control-Allow-Origin為*的,這里的一切設置都會失效。

    如何優化

    如果不想讓每個CORS復雜請求都出兩次請求,可以設置Access-Control-Max-Age這個屬性。讓瀏覽器緩存,在緩存的有效期內,所有options請求都不會發送。優化性能。

    app.use(async?(ctx,?next)?=>?{
    ????//?允許來息所有域名的請求
    ????ctx.set('Access-Control-Allow-Origin',?'*')

    ????//?允許HTTP請求的方法
    ????ctx.set('Access-Control-Allow-Methods',?'OPTIONS,DELETE,GET,PUT,POST')

    ????//?表明服務器支持所有頭信息字段
    ????ctx.set('Access-Control-Allow-Headers',?'x-requested-with,?accept,?origin,?content-type,?token')

    ????//?設置請求preflight緩存的時間,單位?秒
    ????ctx.set('Access-Control-Max-Age',?10)
    ????})

    其它問題

    這里我測試的時候遇到一個問題:在火狐瀏覽器上options請求能顯示出來,但是在chrome瀏覽器里就不能顯示,不知道為什么

    總結

    在當前,前后端分離的開發模式下,跨域問題是經常遇到的,OPTIONS只不過CORS機制當中的一個預檢測請求。而且這個請求是整個CORS機制控制的,并不能在前端用代碼進行控制。主要作用:

  • 檢測服務器支持的請求方法
  • CORS 中的預檢請求
  • 另外給個在線的curl命令工具:https://reqbin.com/req/jecm0tqu/options-request-example

    參考

    • MDN OPTIONS請求
    • HTTP訪問控制(CORS)
    • 跨域資源共享 CORS 詳解- 跨域資源共享 CORS 詳解
    • 玩轉Koa -- koa-router

    總結

    以上是生活随笔為你收集整理的ios 请求头设置token_HTTP中的OPTIONS请求的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。