精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

聊聊Axios中值得學習的核心知識點

開發 前端
Axios 是一個基于 Promise 的 HTTP 客戶端,同時支持瀏覽器和 Node.js 環境。它是一個優秀的 HTTP 客戶端,被廣泛地應用在大量的 Web 項目中。

Axios 是一個基于 Promise 的 HTTP 客戶端,同時支持瀏覽器和 Node.js 環境。它是一個優秀的 HTTP 客戶端,被廣泛地應用在大量的 Web 項目中。

由上圖可知,Axios 項目的 Star 數為 「77.9K」,Fork 數也高達 「7.3K」,是一個很優秀的開源項目,所以接下來阿寶哥將帶大家一起來分析 Axios 項目中一些值得借鑒的地方。

閱讀完本文,你將了解以下內容:

  •  HTTP 攔截器的設計與實現;
  •  HTTP 適配器的設計與實現;
  •  如何防御 CSRF 攻擊。

下面我們從簡單的開始,先來了解一下 Axios。

一、Axios 簡介

Axios 是一個基于 Promise 的 HTTP 客戶端,擁有以下特性:

  •  支持 Promise API;
  •  能夠攔截請求和響應;
  •  能夠轉換請求和響應數據;
  •  客戶端支持防御 CSRF 攻擊;
  •  同時支持瀏覽器和 Node.js 環境;
  •  能夠取消請求及自動轉換 JSON 數據。

在瀏覽器端 Axios 支持大多數主流的瀏覽器,比如 Chrome、Firefox、Safari 和 IE 11。此外,Axios 還擁有自己的生態:

(數據來源 —— https://github.com/axios/axios/blob/master/ECOSYSTEM.md

簡單介紹完 Axios,我們來分析一下它提供的一個核心功能 —— 攔截器。

二、HTTP 攔截器的設計與實現

2.1 攔截器簡介

對于大多數 SPA 應用程序來說, 通常會使用 token 進行用戶的身份認證。這就要求在認證通過后,我們需要在每個請求上都攜帶認證信息。針對這個需求,為了避免為每個請求單獨處理,我們可以通過封裝統一的 request 函數來為每個請求統一添加 token 信息。

但后期如果需要為某些 GET 請求設置緩存時間或者控制某些請求的調用頻率的話,我們就需要不斷修改 request 函數來擴展對應的功能。此時,如果在考慮對響應進行統一處理的話,我們的 request 函數將變得越來越龐大,也越來越難維護。那么對于這個問題,該如何解決呢?Axios 為我們提供了解決方案 —— 攔截器。

Axios 是一個基于 Promise 的 HTTP 客戶端,而 HTTP 協議是基于請求和響應:

所以 Axios 提供了請求攔截器和響應攔截器來分別處理請求和響應,它們的作用如下:

  •  請求攔截器:該類攔截器的作用是在請求發送前統一執行某些操作,比如在請求頭中添加 token 字段。
  •  響應攔截器:該類攔截器的作用是在接收到服務器響應后統一執行某些操作,比如發現響應狀態碼為 401 時,自動跳轉到登錄頁。

在 Axios 中設置攔截器很簡單,通過 axios.interceptors.request 和 axios.interceptors.response 對象提供的 use 方法,就可以分別設置請求攔截器和響應攔截器: 

  1. // 添加請求攔截器  
  2. axios.interceptors.request.use(function (config) {  
  3.   config.headers.token = 'added by interceptor' 
  4.   return config;  
  5. });  
  6. // 添加響應攔截器  
  7. axios.interceptors.response.use(function (data) {  
  8.   datadata.data = data.data + ' - modified by interceptor';  
  9.   return data;  
  10. }); 

那么攔截器是如何工作的呢?在看具體的代碼之前,我們先來分析一下它的設計思路。Axios 的作用是用于發送 HTTP 請求,而請求攔截器和響應攔截器的本質都是一個實現特定功能的函數。

我們可以按照功能把發送 HTTP 請求拆解成不同類型的子任務,比如有用于處理請求配置對象的子任務,用于發送 HTTP 請求的子任務和用于處理響應對象的子任務。當我們按照指定的順序來執行這些子任務時,就可以完成一次完整的 HTTP 請求。

了解完這些,接下來我們將從 「任務注冊、任務編排和任務調度」 三個方面來分析 Axios 攔截器的實現。

2.2 任務注冊

通過前面攔截器的使用示例,我們已經知道如何注冊請求攔截器和響應攔截器,其中請求攔截器用于處理請求配置對象的子任務,而響應攔截器用于處理響應對象的子任務。要搞清楚任務是如何注冊的,就需要了解 axios 和 axios.interceptors 對象。 

  1. // lib/axios.js  
  2. function createInstance(defaultConfig) {  
  3.   var context = new Axios(defaultConfig);  
  4.   var instance = bind(Axios.prototype.request, context);  
  5.   // Copy axios.prototype to instance  
  6.   utils.extend(instance, Axios.prototype, context);  
  7.   // Copy context to instance  
  8.   utils.extend(instance, context);  
  9.   return instance;  
  10.  
  11. // Create the default instance to be exported  
  12. var axios = createInstance(defaults); 

在 Axios 的源碼中,我們找到了 axios 對象的定義,很明顯默認的 axios 實例是通過 createInstance 方法創建的,該方法最終返回的是 Axios.prototype.request 函數對象。同時,我們發現了 Axios 的構造函數: 

  1. // lib/core/Axios.js  
  2. function Axios(instanceConfig) {  
  3.   this.defaults = instanceConfig 
  4.   this.interceptors = {  
  5.     request: new InterceptorManager(),  
  6.     response: new InterceptorManager()  
  7.   }; 

在構造函數中,我們找到了 axios.interceptors 對象的定義,也知道了 interceptors.request 和 interceptors.response 對象都是 InterceptorManager 類的實例。因此接下來,進一步分析 InterceptorManager 構造函數及相關的 use 方法就可以知道任務是如何注冊的: 

  1. // lib/core/InterceptorManager.js  
  2. function InterceptorManager() {  
  3.   this.handlers = [];  
  4.  
  5. InterceptorManager.prototype.use = function use(fulfilled, rejected) {  
  6.   this.handlers.push({  
  7.     fulfilled: fulfilled,  
  8.     rejected: rejected  
  9.   });  
  10.   // 返回當前的索引,用于移除已注冊的攔截器  
  11.   return this.handlers.length - 1;  
  12. }; 

通過觀察 use 方法,我們可知注冊的攔截器都會被保存到 InterceptorManager 對象的 handlers 屬性中。下面我們用一張圖來總結一下 Axios 對象與 InterceptorManager 對象的內部結構與關系:

2.3 任務編排

現在我們已經知道如何注冊攔截器任務,但僅僅注冊任務是不夠,我們還需要對已注冊的任務進行編排,這樣才能確保任務的執行順序。這里我們把完成一次完整的 HTTP 請求分為處理請求配置對象、發起 HTTP 請求和處理響應對象 3 個階段。

接下來我們來看一下 Axios 如何發請求的: 

  1. axios({  
  2.   url: '/hello',  
  3.   method: 'get',  
  4. }).then(res => 
  5.   console.log('axios res: ', res)  
  6.   console.log('axios res.data: ', res.data)  
  7. }) 

通過前面的分析,我們已經知道 axios 對象對應的是 Axios.prototype.request 函數對象,該函數的具體實現如下: 

  1. // lib/core/Axios.js  
  2. Axios.prototype.request = function request(config) {  
  3.   config = mergeConfig(this.defaults, config);  
  4.   // 省略部分代碼  
  5.   var chain = [dispatchRequest, undefined];  
  6.   var promise = Promise.resolve(config);  
  7.   // 任務編排  
  8.   this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {  
  9.     chain.unshift(interceptor.fulfilled, interceptor.rejected); 
  10.    });  
  11.   this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {  
  12.     chain.push(interceptor.fulfilled, interceptor.rejected);  
  13.   });  
  14.   // 任務調度  
  15.   while (chain.length) {  
  16.     promisepromise = promise.then(chain.shift(), chain.shift());  
  17.   }  
  18.   return promise;  
  19. }; 

任務編排的代碼比較簡單,我們來看一下任務編排前和任務編排后的對比圖:

2.4 任務調度

任務編排完成后,要發起 HTTP 請求,我們還需要按編排后的順序執行任務調度。在 Axios 中具體的調度方式很簡單,具體如下所示: 

  1. // lib/core/Axios.js  
  2. xios.prototype.request = function request(config) {  
  3.  // 省略部分代碼 
  4.   var promise = Promise.resolve(config);  
  5.  while (chain.length) {  
  6.    promisepromise = promise.then(chain.shift(), chain.shift());  
  7.  } 

因為 chain 是數組,所以通過 while 語句我們就可以不斷地取出設置的任務,然后組裝成 Promise 調用鏈從而實現任務調度,對應的處理流程如下圖所示:

下面我們來回顧一下 Axios 攔截器完整的使用流程: 

  1. // 添加請求攔截器 —— 處理請求配置對象  
  2. axios.interceptors.request.use(function (config) {  
  3.   config.headers.token = 'added by interceptor' 
  4.   return config;  
  5. }); 
  6. // 添加響應攔截器 —— 處理響應對象  
  7. axios.interceptors.response.use(function (data) {  
  8.   datadata.data = data.data + ' - modified by interceptor';  
  9.   return data;  
  10. });  
  11. axios({  
  12.   url: '/hello',  
  13.   method: 'get',  
  14. }).then(res => 
  15.   console.log('axios res.data: ', res.data)  
  16. }) 

介紹完 Axios 的攔截器,我們來總結一下它的優點。Axios 通過提供攔截器機制,讓開發者可以很容易在請求的生命周期中自定義不同的處理邏輯。

此外,也可以通過攔截器機制來靈活地擴展 Axios 的功能,比如 Axios 生態中列舉的 axios-response-logger 和 axios-debug-log 這兩個庫。

參考 Axios 攔截器的設計模型,我們就可以抽出以下通用的任務處理模型:

三、HTTP 適配器的設計與實現

3.1 默認 HTTP 適配器

Axios 同時支持瀏覽器和 Node.js 環境,對于瀏覽器環境來說,我們可以通過 XMLHttpRequest 或 fetch API 來發送 HTTP 請求,而對于 Node.js 環境來說,我們可以通過 Node.js 內置的 http 或 https 模塊來發送 HTTP 請求。

為了支持不同的環境,Axios 引入了適配器。在 HTTP 攔截器設計部分,我們看到了一個 dispatchRequest 方法,該方法用于發送 HTTP 請求,它的具體實現如下所示: 

  1. // lib/core/dispatchRequest.js  
  2. module.exports = function dispatchRequest(config) {  
  3.   // 省略部分代碼  
  4.   var adapter = config.adapter || defaults.adapter;  
  5.   return adapter(config).then(function onAdapterResolution(response) {  
  6.     // 省略部分代碼  
  7.     return response;  
  8.   }, function onAdapterRejection(reason) {  
  9.     // 省略部分代碼  
  10.     return Promise.reject(reason);  
  11.   });  
  12. }; 

通過查看以上的 dispatchRequest 方法,我們可知 Axios 支持自定義適配器,同時也提供了默認的適配器。對于大多數場景,我們并不需要自定義適配器,而是直接使用默認的適配器。因此,默認的適配器就會包含瀏覽器和 Node.js 環境的適配代碼,其具體的適配邏輯如下所示: 

  1. // lib/defaults.js  
  2. var defaults = {  
  3.   adapter: getDefaultAdapter(),  
  4.   xsrfCookieName: 'XSRF-TOKEN',  
  5.   xsrfHeaderName: 'X-XSRF-TOKEN',  
  6.   //...  
  7.  
  8. function getDefaultAdapter() {  
  9.   var adapter;  
  10.   if (typeof XMLHttpRequest !== 'undefined') {  
  11.     // For browsers use XHR adapter  
  12.     adapter = require('./adapters/xhr');  
  13.   } else if (typeof process !== 'undefined' &&   
  14.     Object.prototype.toString.call(process) === '[object process]') {  
  15.     // For node use HTTP adapter  
  16.     adapter = require('./adapters/http');  
  17.   }  
  18.   return adapter;  

在 getDefaultAdapter 方法中,首先通過平臺中特定的對象來區分不同的平臺,然后再導入不同的適配器,具體的代碼比較簡單,這里就不展開介紹。

3.2 自定義適配器

其實除了默認的適配器外,我們還可以自定義適配器。那么如何自定義適配器呢?這里我們可以參考 Axios 提供的示例: 

  1. var settle = require('./../core/settle');  
  2. module.exports = function myAdapter(config) {  
  3.   // 當前時機點:  
  4.   //  - config配置對象已經與默認的請求配置合并  
  5.   //  - 請求轉換器已經運行  
  6.   //  - 請求攔截器已經運行  
  7.   // 使用提供的config配置對象發起請求  
  8.   // 根據響應對象處理Promise的狀態  
  9.   return new Promise(function(resolve, reject) {  
  10.     var response = { 
  11.        data: responseData,  
  12.       status: request.status,  
  13.       statusText: request.statusText,  
  14.       headers: responseHeaders,  
  15.       config: config,  
  16.       request: request  
  17.     };  
  18.     settle(resolve, reject, response);  
  19.     // 此后:  
  20.     //  - 響應轉換器將會運行  
  21.     //  - 響應攔截器將會運行  
  22.   });  

在以上示例中,我們主要關注轉換器、攔截器的運行時機點和適配器的基本要求。比如當調用自定義適配器之后,需要返回 Promise 對象。這是因為 Axios 內部是通過 Promise 鏈式調用來完成請求調度,不清楚的小伙伴可以重新閱讀 “攔截器的設計與實現” 部分的內容。

現在我們已經知道如何自定義適配器了,那么自定義適配器有什么用呢?在 Axios 生態中,阿寶哥發現了 axios-mock-adapter 這個庫,該庫通過自定義適配器,讓開發者可以輕松地模擬請求。對應的使用示例如下所示: 

  1. var axios = require("axios");  
  2. var MockAdapter = require("axios-mock-adapter");  
  3. // 在默認的Axios實例上設置mock適配器  
  4. var mock = new MockAdapter(axios);  
  5. // 模擬 GET /users 請求  
  6. mock.onGet("/users").reply(200, {  
  7.   users: [{ id: 1, name: "John Smith" }],  
  8. });  
  9. axios.get("/users").then(function (response) {  
  10.   console.log(response.data);  
  11. }); 

對 MockAdapter 感興趣的小伙伴,可以自行了解一下 axios-mock-adapter 這個庫。到這里我們已經介紹了 Axios 的攔截器與適配器,下面阿寶哥用一張圖來總結一下 Axios 使用請求攔截器和響應攔截器后,請求的處理流程:

四、CSRF 防御

4.1 CSRF 簡介

「跨站請求偽造」(Cross-site request forgery),通常縮寫為 「CSRF」 或者 「XSRF」, 是一種挾制用戶在當前已登錄的 Web 應用程序上執行非本意的操作的攻擊方法。

跨站請求攻擊,簡單地說,是攻擊者通過一些技術手段欺騙用戶的瀏覽器去訪問一個自己曾經認證過的網站并運行一些操作(如發郵件,發消息,甚至財產操作如轉賬和購買商品)。由于瀏覽器曾經認證過,所以被訪問的網站會認為是真正的用戶操作而去運行。

為了讓小伙伴更好地理解上述的內容,阿寶哥畫了一張跨站請求攻擊示例圖:

在上圖中攻擊者利用了 Web 中用戶身份驗證的一個漏洞:「簡單的身份驗證只能保證請求發自某個用戶的瀏覽器,卻不能保證請求本身是用戶自愿發出的」。既然存在以上的漏洞,那么我們應該怎么進行防御呢?接下來我們來介紹一些常見的 CSRF 防御措施。

4.2 CSRF 防御措施

4.2.1 檢查 Referer 字段

HTTP 頭中有一個 Referer 字段,這個字段用以標明請求來源于哪個地址。「在處理敏感數據請求時,通常來說,Referer 字段應和請求的地址位于同一域名下」。

以示例中商城操作為例,Referer 字段地址通常應該是商城所在的網頁地址,應該也位于 www.semlinker.com 之下。而如果是 CSRF 攻擊傳來的請求,Referer 字段會是包含惡意網址的地址,不會位于 www.semlinker.com 之下,這時候服務器就能識別出惡意的訪問。

這種辦法簡單易行,僅需要在關鍵訪問處增加一步校驗。但這種辦法也有其局限性,因其完全依賴瀏覽器發送正確的 Referer 字段。雖然 HTTP 協議對此字段的內容有明確的規定,但并無法保證來訪的瀏覽器的具體實現,亦無法保證瀏覽器沒有安全漏洞影響到此字段。并且也存在攻擊者攻擊某些瀏覽器,篡改其 Referer 字段的可能。

4.2.2 同步表單 CSRF 校驗

CSRF 攻擊之所以能夠成功,是因為服務器無法區分正常請求和攻擊請求。針對這個問題我們可以要求所有的用戶請求都攜帶一個 CSRF 攻擊者無法獲取到的 token。對于 CSRF 示例圖中的表單攻擊,我們可以使用 「同步表單 CSRF 校驗」 的防御措施。

「同步表單 CSRF 校驗」 就是在返回頁面時將 token 渲染到頁面上,在 form 表單提交的時候通過隱藏域或者作為查詢參數把 CSRF token 提交到服務器。比如,在同步渲染頁面時,在表單請求中增加一個 _csrf 的查詢參數,這樣當用戶在提交這個表單的時候就會將 CSRF token 提交上來: 

  1. <form method="POST" action="/upload?_csrf={{由服務端生成}}" enctype="multipart/form-data">  
  2.   用戶名: <input name="name" />  
  3.   選擇頭像: <input name="file" type="file" />  
  4.   <button type="submit">提交</button>  
  5. </form> 

4.2.3 雙重 Cookie 防御

「雙重 Cookie 防御」 就是將 token 設置在 Cookie 中,在提交(POST、PUT、PATCH、DELETE)等請求時提交 Cookie,并通過請求頭或請求體帶上 Cookie 中已設置的 token,服務端接收到請求后,再進行對比校驗。

下面我們以 jQuery 為例,來看一下如何設置 CSRF token: 

  1. let csrfToken = Cookies.get('csrfToken');  
  2. function csrfSafeMethod(method) {  
  3.   // 以下HTTP方法不需要進行CSRF防護  
  4.   return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));  
  5.  
  6. $.ajaxSetup({  
  7.   beforeSend: function(xhr, settings) {  
  8.     if (!csrfSafeMethod(settings.type) && !this.crossDomain) {  
  9.       xhr.setRequestHeader('x-csrf-token', csrfToken);  
  10.     }  
  11.   },  
  12. }); 

介紹完 CSRF 攻擊的方式和防御手段,最后我們來看一下 Axios 是如何防御 CSRF 攻擊的。

4.3 Axios CSRF 防御

Axios 提供了 xsrfCookieName 和 xsrfHeaderName 兩個屬性來分別設置 CSRF 的 Cookie 名稱和 HTTP 請求頭的名稱,它們的默認值如下所示: 

  1. // lib/defaults.js  
  2. var defaults = {  
  3.   adapter: getDefaultAdapter(),  
  4.   // 省略部分代碼  
  5.   xsrfCookieName: 'XSRF-TOKEN',  
  6.   xsrfHeaderName: 'X-XSRF-TOKEN',  
  7. }; 

前面我們已經知道在不同的平臺中,Axios 使用不同的適配器來發送 HTTP 請求,這里我們以瀏覽器平臺為例,來看一下 Axios 如何防御 CSRF 攻擊: 

  1. // lib/adapters/xhr.js  
  2. module.exports = function xhrAdapter(config) {  
  3.   return new Promise(function dispatchXhrRequest(resolve, reject) {  
  4.     var requestHeaders = config.headers;   
  5.     var request = new XMLHttpRequest();  
  6.     // 省略部分代碼   
  7.      // 添加xsrf頭部  
  8.     if (utils.isStandardBrowserEnv()) {  
  9.       var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?  
  10.         cookies.read(config.xsrfCookieName) :  
  11.         undefined; 
  12.       if (xsrfValue) {  
  13.         requestHeaders[config.xsrfHeaderName] = xsrfValue;  
  14.       }  
  15.     }  
  16.     request.send(requestData);  
  17.   });  
  18. }; 

看完以上的代碼,相信小伙伴們就已經知道答案了,原來 Axios 內部是使用 「雙重 Cookie 防御」 的方案來防御 CSRF 攻擊。

好的,到這里本文的主要內容都已經介紹完了,其實 Axios 項目還有一些值得我們借鑒的地方,比如 CancelToken 的設計、異常處理機制等,感興趣的小伙伴可以自行學習一下。 

 

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2021-01-15 08:35:49

Zookeeper

2020-11-06 00:50:16

JavaClassLoaderJVM

2021-12-30 08:17:27

Springboot數據訪問DataSourceB

2025-01-07 14:10:46

SpringBoot開發Java

2021-04-13 08:25:12

測試開發Java注解Spring

2021-01-06 13:52:19

zookeeper開源分布式

2020-05-19 14:40:08

Linux互聯網核心

2024-11-04 09:00:00

Java開發

2025-03-26 11:30:40

2024-04-23 14:25:16

Python備忘清單

2025-05-13 08:10:00

MySQL二進制日志binlog

2021-01-18 10:33:53

Java反射模塊

2022-10-29 08:55:19

頁面react

2022-04-08 07:51:31

JavaJVM垃圾回收

2024-06-04 14:07:00

2020-10-28 08:26:23

Vue源碼開發

2023-08-07 14:44:56

Socket文件描述符

2021-12-31 07:48:58

Vue3 插件Vue應用

2010-06-17 16:42:04

UML

2010-07-27 15:49:28

Flex
點贊
收藏

51CTO技術棧公眾號

美女日批在线观看| 中文字幕日韩精品一区二区| 精品国产免费观看| 深夜福利久久| 欧美日韩大陆在线| 免费看日b视频| 天堂资源中文在线| 美女视频一区二区| 久久久久国产视频| 亚洲黄色免费视频| 亚洲午夜免费| 在线观看av一区| 99久久久无码国产精品性色戒| 国精产品一品二品国精品69xx| 亚洲自拍另类| 超碰91人人草人人干| 中文字幕av观看| 黄色成人小视频| 亚洲v日本v欧美v久久精品| 日本一区二区三区免费看| 国产精品自产拍| 久久精品亚洲| 欧美日韩第一视频| 国产又黄又粗的视频| 白白在线精品| 欧美日韩成人综合| 97在线免费公开视频| 高h视频在线观看| 久久久精品日韩欧美| 97av影视网在线观看| 怡红院男人天堂| 一区二区三区精品视频在线观看| 久久综合伊人77777| 久久成人激情视频| 日韩在线观看视频一区二区| 99久久免费精品国产72精品九九| 欧美亚洲免费在线一区| 黄色成人在线看| 黄色网在线免费观看| 2020日本不卡一区二区视频| 97超级在线观看免费高清完整版电视剧| 人妻丰满熟妇av无码区| 亚洲精选国产| 欧美成人精品xxx| 卡一卡二卡三在线观看| 伊人成综合网伊人222| 精品成a人在线观看| 手机精品视频在线| 性欧美video另类hd尤物| 欧美午夜女人视频在线| 国产va亚洲va在线va| а天堂中文在线官网| 国产精品久久久久aaaa| 偷拍视频一区二区| 嫩草研究院在线观看| 福利一区二区在线| 亚洲free性xxxx护士白浆| 亚洲天堂男人网| 男人的j进女人的j一区| 国产精品久久久久久久久久久久 | www.久久久.com| 欧洲中文字幕精品| 亚洲精品视频导航| 韩日一区二区| 欧美色综合天天久久综合精品| 精品国产成人av在线免| 欧美7777| 在线观看视频一区二区欧美日韩| 妺妺窝人体色www在线观看| 在线看欧美视频| 欧美日免费三级在线| 在线观看的毛片| 国产精品传媒麻豆hd| 欧美日韩免费高清一区色橹橹| 日韩av手机版| 综合久草视频| 欧美成人bangbros| 国产精品手机在线观看| 亚洲精华一区二区三区| 亚洲视频在线观看| 日韩欧美视频免费观看| 婷婷亚洲五月| 久久久久久久香蕉网| 国产欧美日韩另类| 亚洲欧美清纯在线制服| 国产精品极品尤物在线观看 | 欧美三级电影精品| 91精品999| 91精品国产自产在线丝袜啪 | aa片在线观看视频在线播放| 国内精品视频在线观看| 久久精品国产成人精品| 久久久久久久国产精品毛片| 亚洲免费网站| 国产日本欧美一区| www.亚洲欧美| 久久亚洲精品小早川怜子| 亚洲国产精品日韩| 国产亚av手机在线观看| 在线观看视频一区二区欧美日韩| 天天操精品视频| 琪琪久久久久日韩精品| 中文字幕欧美日韩精品| 久久久久无码国产精品| 久久中文精品| 99国产在线| 国产精品秘入口| 一区二区三区毛片| 一区二区三区入口| 国产精品一区二区中文字幕| 在线观看日韩视频| 精品无码免费视频| 久热成人在线视频| 国产综合18久久久久久| 日本在线免费网| 欧美日韩中文在线| 一级片免费在线观看视频| 免费看成人哺乳视频网站| 九九热99久久久国产盗摄| 国产真人无遮挡作爱免费视频| 丁香网亚洲国际| 亚洲欧洲一区二区福利| 蜜桃视频www网站在线观看| 777xxx欧美| 扒开jk护士狂揉免费| 午夜视频精品| 国产一区二区丝袜| 国产免费a∨片在线观看不卡| 亚洲在线免费播放| 91欧美一区二区三区| 日韩在线观看| 国产精品aaa| 水莓100在线视频| 亚洲一区二区影院| 午夜大片在线观看| 成人在线免费观看视频| 国内精品一区二区三区四区| 国产白浆在线观看| 国产精品免费aⅴ片在线观看| 国产深夜男女无套内射| 18国产精品| 久久亚洲国产精品| 在线观看免费视频一区| 国产亚洲精久久久久久| 成人免费在线小视频| 加勒比色老久久爱综合网| 欧美肥臀大乳一区二区免费视频| 91肉色超薄丝袜脚交一区二区| caoporn国产一区二区| 成人在线免费高清视频| 欧洲大片精品免费永久看nba| 日韩视频免费在线| 亚洲综合精品国产一区二区三区 | 99自拍偷拍视频| 日韩精品一区第一页| 欧美成人dvd在线视频| 天堂电影一区| 亚洲欧美日韩精品久久奇米色影视| 国产精品日日夜夜| 99久久伊人精品| 极品美女扒开粉嫩小泬| 欧美理论电影在线精品| 777午夜精品福利在线观看| 污视频在线免费| 五月婷婷欧美视频| 波多野结衣一本| 视频一区二区不卡| 亚洲精品一区二区三区av| 久久99国产精品二区高清软件| 日韩在线观看免费高清完整版| 一本色道久久综合精品婷婷| 亚洲色图视频网| 成人啪啪18免费游戏链接| 今天的高清视频免费播放成人| 国产女主播一区二区| 成人av三级| 视频在线一区二区| 国产三级精品在线观看| 亚洲国产日韩精品| 国产成人无码精品久久二区三| 日本aⅴ亚洲精品中文乱码| 最新精品视频| 成人三级av在线| 秋霞av国产精品一区| 91福利在线视频| 日韩精品中午字幕| 天堂网中文字幕| 亚洲三级视频在线观看| xxxxxx黄色| 美腿丝袜亚洲三区| 欧美激情亚洲天堂| 国产一区二区观看| 91在线观看免费网站| а√在线中文在线新版| 在线成人中文字幕| 亚洲av无码乱码国产麻豆 | 尤物yw午夜国产精品视频明星| 国产女人18毛片水真多| 婷婷成人综合网| 黑人狂躁日本娇小| 99久久综合色| 久久成年人网站| 久久xxxx精品视频| 久久久久久久久网| 国产又粗又大又爽视频| 999在线观看精品免费不卡网站| 日本在线观看一区| 人人爱人人干婷婷丁香亚洲| 热草久综合在线| 亚洲图区一区| 在线观看亚洲视频| 亚洲乱码国产乱码精品精软件| 一本大道久久a久久综合| 欧美日韩在线视频免费| 中文字幕免费一区| 日韩免费高清一区二区| 国产精品18久久久久久久久久久久| 日韩免费毛片视频| 在线视频观看日韩| 免费国产成人看片在线| 国产欧美日韩一区二区三区四区 | 日韩视频一二区| 国产精品成人va在线观看| 国产精品蜜臀| 日韩亚洲欧美中文在线| 黄色片在线免费看| 亚洲国产99精品国自产| 99热这里只有精品在线| 欧美视频在线一区二区三区 | 在线观看一区二区视频| 亚洲国产综合久久| 亚洲色欲色欲www在线观看| 亚洲欧美va天堂人熟伦| 91网站在线观看视频| 极品白嫩的小少妇| 国产乱码精品一区二区三区av| 亚洲国产精品三区| 日日摸夜夜添夜夜添国产精品| 日本网站免费在线观看| 136国产福利精品导航网址| av磁力番号网| 欧美一区免费| dy888午夜| 91成人看片| 欧洲xxxxx| 自产国语精品视频| 欧洲美女和动交zoz0z| 欧美gayvideo| 影音欧美亚洲| 99精品视频精品精品视频| 先锋影音网一区| 欧美肉体xxxx裸体137大胆| 蜜桃av色综合| 亚洲区小说区图片区qvod按摩 | www.国产视频.com| 日本在线不卡视频| 日日碰狠狠丁香久燥| 中文一区在线| 亚洲色成人一区二区三区小说| 国产亚洲一区在线| 国产1区2区在线| 久久久夜精品| 国产真人无码作爱视频免费| 日韩av午夜在线观看| 国产又粗又长又大的视频| 男女男精品视频| www.欧美激情.com| 国产91富婆露脸刺激对白| 麻豆精品国产传媒av| 91最新地址在线播放| 美女被到爽高潮视频| 亚洲国产电影在线观看| 黑人操日本美女| 一区二区三区免费在线观看| 国产无遮挡aaa片爽爽| 欧美午夜精品久久久久久人妖| 亚洲第一区av| 91精选在线观看| 空姐吹箫视频大全| 亚洲欧美一区二区精品久久久| 五月婷婷在线视频| 欧美成人精品在线视频| av中文字幕在线观看第一页| 日本韩国在线不卡| 中文字幕成人| 国内精品国语自产拍在线观看| 欧美日韩精品在线一区| 日本一道在线观看| 乱码第一页成人| 天天做天天干天天操| kk眼镜猥琐国模调教系列一区二区| 少妇久久久久久久久久| 亚洲视频1区2区| 成人免费a视频| 欧美剧情电影在线观看完整版免费励志电影| 国产精品呻吟久久| 日韩激情视频在线播放| 日本免费在线观看| 97在线观看免费| 久久91超碰青草在哪里看| 国产一区二区精品在线| 色97色成人| 国产91xxx| 国产专区欧美精品| 欧美成人午夜精品免费| 亚洲免费三区一区二区| 好看的av在线| 日韩欧美国产精品| 日本在线免费播放| 欧美中在线观看| 综合久久成人| 在线观看日韩羞羞视频| 国产日韩视频| 亚洲成人av免费观看| 中文字幕免费不卡在线| 91精品国产乱码在线观看| 制服丝袜亚洲精品中文字幕| 青青草视频免费在线观看| 欧美激情视频在线免费观看 欧美视频免费一| 女生影院久久| 久久国产精品99久久久久久丝袜| 中文字幕一区二区三区欧美日韩 | 成人软件在线观看| 国产精品免费一区二区三区四区 | 制服丝袜综合日韩欧美| 男人的天堂亚洲在线| 成人午夜精品无码区| 亚洲精品免费播放| 97国产成人无码精品久久久| 亚洲三级免费看| 三级在线看中文字幕完整版| 成人av免费在线看| 天天操综合网| 日韩av一卡二卡三卡| 亚洲国产精品成人综合| 五月婷婷六月婷婷| 亚洲欧美中文字幕在线一区| 1区2区3区在线| 国产精品国产精品| 欧美日韩国产一区精品一区| 中文字幕avav| 亚洲欧美视频在线观看| 97国产成人无码精品久久久| 丝袜情趣国产精品| 一区在线影院| 亚洲国产高清国产精品| 蜜臂av日日欢夜夜爽一区| 国产欧美一区二区三区在线观看视频 | 国产精品麻豆免费版| 激情视频一区| 无码人妻aⅴ一区二区三区玉蒲团| 一区二区三区高清| 黄频网站在线观看| 97视频在线观看视频免费视频| 人人精品亚洲| 国产三区在线视频| 国产视频一区二区在线| 超碰在线97观看| 夜夜嗨av一区二区三区免费区| 国产成人77亚洲精品www| 中文字幕在线观看一区二区三区| 精品综合久久久久久8888| 天天操夜夜操av| 欧美一级欧美三级在线观看| 色呦呦在线播放| 精品1区2区| 久久精品综合| 国产精品综合激情| 91麻豆精品国产91久久久久久| 在线播放免费av| 国产三区二区一区久久| 男女av一区三区二区色多| 男人的天堂av网| 欧美美女一区二区三区| 怡红院红怡院欧美aⅴ怡春院| 国产99在线播放| 午夜一级久久| 狂野欧美性猛交| 日韩视频免费观看高清完整版在线观看| 美女尤物在线视频| 免费成人av网站| 久久99日本精品| 加勒比av在线播放| 亚洲精品天天看| 免费一区二区三区四区| 国产成人在线小视频| 97se亚洲国产综合在线| 亚洲专区第一页| 97国产suv精品一区二区62| 国产中文字幕一区二区三区| 91香蕉视频免费看| 欧美日韩亚洲激情| 午夜视频成人| 精品乱码一区二区三区| 久久99精品久久久久婷婷| 免费在线观看黄色av| 亚洲人成网站777色婷婷| 白嫩亚洲一区二区三区| 欧美视频在线观看网站| 成人欧美一区二区三区白人|