<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      WCF進階:擴展EndpointBehavior實現全局參數驗證

         上一篇文章WCF進階:擴展bindingElementExtensions支持對稱加密傳輸闡述了如何擴展BindElementExtension來支持在配置文件中配置服務或者客戶端代理,本文講述另外一種應用,通過實現IEndpointBehavior來全局驗證操作參數,并且進一步產生比較復雜的配置支持的實現。

         WCF中在ClientOperation和DispatchOperation上都有一個名為ParameterInspectors的集合類屬性,這個集合里面存儲的是實現IParameterInspector的參數攔截器,它非常的簡單,只有兩個方法定義:

      using System;
      
      namespace System.ServiceModel.Dispatcher
      {
          // 摘要:
          //     定義自定義參數檢查器實現的協定,有了該協定,就可在客戶端或服務進行調用之前或緊接著其調用,檢查或修改信息。
          public interface IParameterInspector
          {
              // 摘要:
              //     在客戶端調用返回之后、服務響應發送之前調用。
              //
              // 參數:
              //   operationName:
              //     所調用的操作的名稱。
              //
              //   outputs:
              //     任何輸出對象。
              //
              //   returnValue:
              //     操作的返回值。
              //
              //   correlationState:
              //     從 System.ServiceModel.Dispatcher.IParameterInspector.BeforeCall(System.String,System.Object[])
              //     方法返回的任何關聯狀態,或 null。
              void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState);
              //
              // 摘要:
              //     在發送客戶端調用之前、服務響應返回之后調用。
              //
              // 參數:
              //   operationName:
              //     操作的名稱。
              //
              //   inputs:
              //     客戶端傳遞到方法的對象。
              //
              // 返回結果:
              //     System.ServiceModel.Dispatcher.IParameterInspector.AfterCall(System.String,System.Object[],System.Object,System.Object)
              //     中,作為 correlationState 參數返回的關聯狀態。如果您不打算使用關聯狀態,則返回 null。
              object BeforeCall(string operationName, object[] inputs);
          }
      }

      通過該接口的定義,我們能清楚能夠在客戶端發送請求之前,在服務端返回響應之后檢查請求的參數,而在客戶端接受響應之后和服務端發送響應之前能檢查返回值。

      image

      我們實現名為MyParameterValidater的IParameterInspector,通過遍歷規則列表中的驗證器驗證參數,本文實現三種驗證器,NotBlank,Email,Phone分別驗證參數不能為空,為Email格式,為電話號碼或者移動電話格式。具體代碼:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.ServiceModel.Dispatcher;
      using System.Text.RegularExpressions;
      
      namespace RobinLib
      {
          public class MyParameterValidater:IParameterInspector
          {
      
              ICollection<ParameterValidator> Validators
              {
                  get;
                  set;
              }
      
              public MyParameterValidater()
              {
      
              }
      
              public MyParameterValidater(ICollection<ParameterValidator> validators)
              {
                  Validators = validators;
              }
      
              #region IParameterInspector 成員
      
              public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
              {
                  //接到請求或者接到響應后
              }
              private static bool isEmail(string inputEmail)
              { 
                  string strRegex = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
                  Regex re = new Regex(strRegex);
                  if (re.IsMatch(inputEmail))
                      return (true);
                  else
                      return (false);
              }
              /// <summary>
              /// 檢測電話號碼
              /// </summary>
              /// <param name="strPhone"></param>
              /// <returns></returns>
              private static bool checkPhone(string strPhone)
              {
                  if (strPhone == "" || strPhone == null)
                  {
                      return false;
                  }
                  else
                  {
                      string phoneRegWithArea = "^[0][1-9]{2,3}[-]{0,1}[0-9]{5,8}$";
                      string phoneRegNoArea = "^[2-9]{1}[0-9]{5,8}$";
                      if (strPhone.Length > 9)
                      {
                          if (Regex.Match(strPhone, phoneRegWithArea, RegexOptions.Compiled).Success) { return true; } else { return false; }
                      }
                      else
                      {
                          if (Regex.Match(strPhone, phoneRegNoArea, RegexOptions.Compiled).Success) { return true; } else { return false; }
                      }
                  }
              }
              /// <summary>
              /// 檢測手機號碼
              /// </summary>
              /// <param name="s"></param>
              /// <returns></returns>
              private static bool checkMobile(string s)
              {
                  if (s == "" || s == null)
                  {
                      return false;
                  }
                  else
                  {
                      string regu = "^[1][3,5,8][0-9]{9}$";
                      if (Regex.Match(s, regu, RegexOptions.Compiled).Success) { return true; } else { return false; }
      
                  }
              }
              /// <summary>
              /// 檢測電話、手機號碼(組合)
              /// </summary>
              /// <param name="PhoneNum"></param>
              /// <returns></returns>
              private static bool CheckBrokerMobile(string PhoneNum)
              {
                  if (PhoneNum == "" || PhoneNum == null)
                  {
                      return false;
                  }
                  else
                  {
                      if (PhoneNum.Substring(0, 1).ToString() == "1")
                      {
                          if (!checkMobile(PhoneNum)) { return false; } else { return true; }
                      }
                      else
                      {
                          if (!checkPhone(PhoneNum)) { return false; } else { return true; }
                      }
                  }
              }
              public object BeforeCall(string operationName, object[] inputs)
              { 
                  foreach (ParameterValidator pv in Validators)
                  {
                      if (pv.ValidateMethodName == operationName)
                      {
                          if (inputs.Length >= pv.ValidateParameterIndex)
                          {
                              if (pv.ValidateType == "NotBlank")
                              {
                                  if (string.IsNullOrEmpty(inputs[pv.ValidateParameterIndex].ToString()))
                                  {
                                      throw new Exception("操作:"+operationName+"第"+pv.ValidateParameterIndex+"個參數不能為空!");
                                  }
                              }
                              else if (pv.ValidateType == "Email")
                              {
                                  if (!isEmail(inputs[pv.ValidateParameterIndex].ToString()))
                                  {
                                      throw new Exception("操作:" + operationName + "第" + pv.ValidateParameterIndex + "參數必須滿足Email格式!");
                                  }
                              }
                              else if (pv.ValidateType == "Phone")
                              {
                                  if (!CheckBrokerMobile(inputs[pv.ValidateParameterIndex].ToString()))
                                  {
                                      throw new Exception("操作:" + operationName + "第" + pv.ValidateParameterIndex + "參數必須滿足電話號碼或者手機格式!");
                                  }
                              }
                              
                          }
                      }
                  }
                  return null;
              }
      
              #endregion
          }
      }

      驗證器的的類定義為:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      
      namespace RobinLib
      {
          public class ParameterValidator
          {  
              public int ValidateParameterIndex
              {
                  get;
                  set;
              }
      
              public string ValidateMethodName
              {
                  get;
                  set;
              }
              public string ValidateType
              {
                  get;
                  set;
              }
          }
      }

      將此ParameterInspector通過IEndpointBehavior,IOperationBehavior,IServiceBehavior等能將該ParameterInspector添加到ClientOperation和DispatchOperation中。我們實現的是IEndpointBehavior,代碼為:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.ServiceModel.Description;
      using System.ServiceModel.Dispatcher;
      
      namespace RobinLib
      {
          public class ParameterValidatorBehavior : IEndpointBehavior
          {
              ICollection<ParameterValidator> Validators
              {
                  get;
                  set;
              }
      
              public ParameterValidatorBehavior()
              {
      
              }
      
              public ParameterValidatorBehavior(ICollection<ParameterValidator> validators)
              {
                  Validators = validators;
              }
      
           
              #region IEndpointBehavior 成員
      
              public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
              {
      
              }
      
              public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
              {
                  foreach (ClientOperation op in clientRuntime.Operations)
                  {
                      op.ParameterInspectors.Add(new MyParameterValidater(Validators));
                  }
              }
      
              public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
              {
                  foreach (DispatchOperation dop in endpointDispatcher.DispatchRuntime.Operations)
                  {
                      dop.ParameterInspectors.Add(new MyParameterValidater(Validators));
                  }
              }
      
              public void Validate(ServiceEndpoint endpoint)
              {
      
              }
      
              #endregion
          }
      }

      到此,我們已經能夠直接通過代碼的形式將自定義ParameterValidatorBehavior的應用到客戶端或者服務端Endpoint上。

      但我們還會實現通過配置的形式應用該ParameterValidatorBehavior,首先我們需要解決如何在配置中傳遞ICollection<ParameterValidator> Validators 參數。WCF中配置集合有一個基類,名為:ConfigurationElementCollection,我們應該首先實現一個自定義的ConfigurationElementCollection。集合中的每一個項也會對應配置中的一個ConfigurationElement,這樣我們設計兩個類:ParameterValidatorCollection和ParameterValidatorElement和ParameterValidatorConfigElement用這三個類實現自定義ParameterValidatorBehavior的配置,形式為:

      <parameterValidator>
        <parameterValidators>
          <add name="p1" validateMethodName="AddUser" validateParameterIndex="0" validateType="Email"/>
          <add name="p2" validateMethodName="AddUser" validateParameterIndex="1" validateType="NotBlank"/>
          <add name="p3" validateMethodName="AddUser" validateParameterIndex="2" validateType="Phone"/>
        </parameterValidators>
      </parameterValidator>

      下面給出三個類的代碼實現:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.ServiceModel.Configuration;
      using System.Configuration;
      
      namespace RobinLib
      {
          public sealed class ParameterValidatorElement : BehaviorExtensionElement
          {
      
              public ParameterValidatorElement()
              {
      
              }
               
              [ConfigurationProperty("parameterValidators", IsDefaultCollection = false)]
              public ParameterValidatorCollection ParameterValidators
              {
                  get
                  {
                      ParameterValidatorCollection parameterValidators =
                                     (ParameterValidatorCollection)base["parameterValidators"];
                      return parameterValidators;
      
                  }
              }
      
              public override Type BehaviorType
              {
                  get 
                  {
                      return typeof(ParameterValidatorBehavior); 
                  }
              }
             
              
              
      
              protected override object CreateBehavior()
              {
                  List<ParameterValidator> validators = new List<ParameterValidator>();
                  foreach (ParameterValidatorConfigElement ve in ParameterValidators)
                  {
                      ParameterValidator pv = new ParameterValidator();
                      pv.ValidateMethodName = ve.ValidateMethodName;
                      pv.ValidateParameterIndex = Convert.ToInt32(ve.ValidateParameterIndex);
                      pv.ValidateType = ve.ValidateType;
                      validators.Add(pv);
                  }
                  ParameterValidatorBehavior behavior = new ParameterValidatorBehavior(validators);
                  return behavior;
              } 
          }
      }
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Configuration;
      
      namespace RobinLib
      {
          public class ParameterValidatorCollection : ConfigurationElementCollection
          {
              protected override ConfigurationElement CreateNewElement()
              {
                  return new ParameterValidatorConfigElement();
              }
              protected override ConfigurationElement CreateNewElement(string elementName)
              {
                  return new ParameterValidatorConfigElement(elementName);
              }
              protected override object GetElementKey(ConfigurationElement element)
              {
                  return ((ParameterValidatorConfigElement)element).Name;
              }
              public override ConfigurationElementCollectionType CollectionType
              {
                  get
                  {
                      return ConfigurationElementCollectionType.AddRemoveClearMap;
                  }
              }
      
              public ParameterValidatorConfigElement this[int index]
              {
                  get
                  {
                      return (ParameterValidatorConfigElement)BaseGet(index);
                  }
                  set
                  {
                      if (BaseGet(index) != null)
                      {
                          BaseRemoveAt(index);
                      }
                      BaseAdd(index, value);
                  }
              }
      
              new public ParameterValidatorConfigElement this[string Name]
              {
                  get
                  {
                      return (ParameterValidatorConfigElement)BaseGet(Name);
                  }
              }
      
              public int IndexOf(ParameterValidatorConfigElement validater)
              {
                  return BaseIndexOf(validater);
              }
      
              public void Add(ParameterValidatorConfigElement validater)
              {
                  BaseAdd(validater);
              }
      
              public void Remove(ParameterValidatorConfigElement validater)
              {
                  if (BaseIndexOf(validater) >= 0)
                  {
                      BaseRemove(validater.Name);
                  }
              }
      
              public void RemoveAt(int index)
              {
                  BaseRemoveAt(index);
              }
      
              public void Remove(string name)
              {
                  BaseRemove(name);
              }
      
              public void Clear()
              {
                  BaseClear();
              }
          }
      }
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Configuration;
      
      namespace RobinLib
      {
          public class ParameterValidatorConfigElement : ConfigurationElement
          {
              public ParameterValidatorConfigElement(String newName, String validateParameterIndex, string validateMethodName, string validateType)
              {
                  Name = newName;
                  ValidateParameterIndex = validateParameterIndex;
                  ValidateMethodName = validateMethodName;
                  ValidateType = validateType;
              }
      
              public ParameterValidatorConfigElement(string newName)
              {
                  Name = newName;
              }
      
              public ParameterValidatorConfigElement()
              {
      
              }
      
              [ConfigurationProperty("name")]
              public string Name
              {
                  get
                  {
                      return base["name"] as string;
                  }
                  set
                  {
                      base["name"] = value;
                  }
              }
      
              [ConfigurationProperty("validateParameterIndex")]
              public string ValidateParameterIndex
              {
                  get
                  {
                      return base["validateParameterIndex"] as string;
                  }
                  set
                  {
                      base["validateParameterIndex"] = value;
                  }
              }
      
              [ConfigurationProperty("validateMethodName")]
              public string ValidateMethodName
              {
                  get
                  {
                      return base["validateMethodName"] as string;
                  }
                  set
                  {
                      base["validateMethodName"] = value;
                  }
              }
      
              [ConfigurationProperty("validateType")]
              public string ValidateType
              {
                  get
                  {
                      return base["validateType"] as string;
                  }
                  set
                  {
                      base["validateType"] = value;
                  }
              }
          }
      }

      實現了這些,我們就配置中應用ParameterValidatorBehavior了。好我們先來看下服務契約的設計

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Runtime.Serialization;
      using System.ServiceModel;
      using System.Text;
      
      namespace Robin_Wcf_ParameterValidater_SvcLib
      {
          // 注意: 如果更改此處的類名“IService1”,也必須更新 App.config 中對“IService1”的引用。
          public class Service1 : IService1
          {
              public int AddUser(string email, string pwd, string phone)
              {
                  Console.WriteLine("new user,email:" + email + ",phone" + phone+",pwd="+pwd);
                  return 1;
              } 
          }
      }

      將該服務托管到一個ConsoleApp中并在一個Console中調用。并且在客戶端發送請求和服務端發送響應的時候,要求操作AddUser的參數email必須為Email格式,pwd不能為空,phone是電話或者手機格式。這樣設計好的服務的配置文件為:

      <?xml version="1.0" encoding="utf-8" ?>
      <configuration>
        <system.serviceModel>
          <services>
            <clear/>
            <service name="Robin_Wcf_ParameterValidater_SvcLib.Service1">
              <host>
                <baseAddresses>
                  <add baseAddress="http://127.0.0.1:8081"/>
                </baseAddresses>
              </host>
              <endpoint name="ep" address ="" binding ="basicHttpBinding" contract="Robin_Wcf_ParameterValidater_SvcLib.IService1" behaviorConfiguration="myEpBehavior"/>
            </service>
          </services>
          <behaviors>
            <endpointBehaviors>
              <behavior name="myEpBehavior">
                <parameterValidator>
                  <parameterValidators>
                    <add name="p1" validateMethodName="AddUser" validateParameterIndex="0" validateType="Email"/>
                    <add name="p2" validateMethodName="AddUser" validateParameterIndex="1" validateType="NotBlank"/>
                    <add name="p3" validateMethodName="AddUser" validateParameterIndex="2" validateType="Phone"/>
                  </parameterValidators>
                </parameterValidator>
              </behavior>
            </endpointBehaviors>
          </behaviors>
      
          <extensions>
            <behaviorExtensions>
              <add name="parameterValidator" type="RobinLib.ParameterValidatorElement, RobinLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
            </behaviorExtensions>
          </extensions>
        </system.serviceModel>
      
      </configuration>

      托管代碼為:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.ServiceModel;
      using Robin_Wcf_ParameterValidater_SvcLib;
      
      namespace Robin_Wcf_ParameterValidater_Host
      {
          class Program
          {
              static void Main(string[] args)
              {
                  ServiceHost host = new ServiceHost(typeof(Service1));
                  if (host.Description.Behaviors.Find<System.ServiceModel.Description.ServiceMetadataBehavior>() == null)
                  {
                      System.ServiceModel.Description.ServiceMetadataBehavior svcMetaBehavior = new System.ServiceModel.Description.ServiceMetadataBehavior();
                      svcMetaBehavior.HttpGetEnabled = true;
                      svcMetaBehavior.HttpGetUrl = new Uri("http://127.0.0.1:8001/Mex");
                      host.Description.Behaviors.Add(svcMetaBehavior);
                  }
                  host.Opened += new EventHandler(delegate(object obj, EventArgs e)
                  {
                      Console.WriteLine("服務已經啟動!");
                  });
                  host.Open();
                  Console.Read();
              }
          }
      }

      客戶端配置為:

      <?xml version="1.0" encoding="utf-8" ?>
      <configuration>
        <system.serviceModel>
          <bindings>
            <basicHttpBinding>
              <binding name="ep" closeTimeout="00:01:00" openTimeout="00:01:00"
                  receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
                  bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                  maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                  messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                  useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <security mode="None">
                  <transport clientCredentialType="None" proxyCredentialType="None"
                      realm="">
                    <extendedProtectionPolicy policyEnforcement="Never" />
                  </transport>
                  <message clientCredentialType="UserName" algorithmSuite="Default" />
                </security>
              </binding>
            </basicHttpBinding>
          </bindings>
          <client>
            <endpoint address="http://127.0.0.1:8081/" binding="basicHttpBinding"
                bindingConfiguration="ep" contract="ServiceReference1.IService1"
                name="ep" behaviorConfiguration="myEpBehavior" />
          </client>
          <behaviors>
            <endpointBehaviors>
              <behavior name="myEpBehavior">
                <parameterValidator>
                  <parameterValidators>
                    <add name="p1" validateMethodName="AddUser" validateParameterIndex="0" validateType="Email"/>
                    <add name="p2" validateMethodName="AddUser" validateParameterIndex="1" validateType="NotBlank"/>
                    <add name="p3" validateMethodName="AddUser" validateParameterIndex="2" validateType="Phone"/>
                  </parameterValidators>
                </parameterValidator>
              </behavior>
            </endpointBehaviors>
          </behaviors>
      
          <extensions>
            <behaviorExtensions>
              <add name="parameterValidator" type="RobinLib.ParameterValidatorElement, RobinLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
            </behaviorExtensions>
          </extensions>
        </system.serviceModel>
      </configuration>

      客戶端調用代碼為:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      
      namespace Robin_Wcf_ParameterValidater_ClientApp
      {
          class Program
          {
              static void Main(string[] args)
              {
                  try
                  {
                      System.Threading.Thread.Sleep(6000);
                      ServiceReference1.Service1Client svc = new Robin_Wcf_ParameterValidater_ClientApp.ServiceReference1.Service1Client();
                      svc.AddUser("robinzhang", "", "");
                  }
                  catch(Exception ex)
                  {
                      Console.WriteLine(ex.Message);
                  }
                  try
                  {
                      System.Threading.Thread.Sleep(6000);
                      ServiceReference1.Service1Client svc = new Robin_Wcf_ParameterValidater_ClientApp.ServiceReference1.Service1Client();
                      svc.AddUser("jillzhang@126.com", "123456", "");
                  }
                  catch (Exception ex)
                  {
                      Console.WriteLine(ex.Message);
                  }
                  try
                  {
                      System.Threading.Thread.Sleep(6000);
                      ServiceReference1.Service1Client svc = new Robin_Wcf_ParameterValidater_ClientApp.ServiceReference1.Service1Client();
                      svc.AddUser("jillzhang@126.com", "", "010-88888888");
                  }
                  catch (Exception ex)
                  {
                      Console.WriteLine(ex.Message);
                  }
                  Console.Read();
              }
          }
      }

      運行結果如下:

      image

      項目文件:點擊這里下載

      需要額外注意的是:添加EndpointBehavior有個特別的要求,<add name="parameterValidator" type="RobinLib.ParameterValidatorElement, RobinLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>中的type值必須和ParameterValidatorElement的強類型的表達字符串完全相符,增減空格或者回車都不行,這也可以認為.net framework的一個bug,詳情見:connect.microsoft.com/wcf/feedback/details/216431/wcf-fails-to-find-custom-behaviorextensionelement-if-type-attribute-doesnt-match-exactly,最終都無人能解。也害得我在這上面郁悶了很久,總以為自己的類編寫錯誤了呢,后來才發現原來和配置BindingElementExtension有此區別,希望大家也多多注意,

      posted @ 2010-04-18 19:31  Robin Zhang  閱讀(6408)  評論(7)    收藏  舉報
      主站蜘蛛池模板: 强开小雪的嫩苞又嫩又紧| 亚洲欧美日韩综合久久久| 猫咪AV成人永久网站在线观看| 性欧美VIDEOFREE高清大喷水| 久久综合色一综合色88欧美| 制服丝袜美腿一区二区| 午夜激情小视频一区二区| 日韩精品国产中文字幕| 国产成人精品一区二区三区| 亚洲欧美精品aaaaaa片| 中文午夜乱理片无码| 欧美成人猛片aaaaaaa| 亚洲av不卡电影在线网址最新| 中文字幕国产在线精品| 香港经典a毛片免费观看播放| 亚洲国产aⅴ成人精品无吗| 国产无套内射又大又猛又粗又爽| 成人亚洲av免费在线| 日韩av一区二区精品不卡| 亚洲欧美精品aaaaaa片| 久久久久成人片免费观看蜜芽| 丁香五月婷激情综合第九色| 日本中文字幕在线播放| 最新国产精品拍自在线观看| 国产suv精品一区二区五| 无码精品国产VA在线观看DVD| 镇远县| 97精品国产91久久久久久久| 国产老女人精品免费视频| 欧美在线观看www| 亚洲自拍偷拍福利小视频| 成人福利国产午夜AV免费不卡在线| 日本极品少妇videossexhd| 国产在线精品中文字幕| 撕开奶罩揉吮奶头高潮av| 无码日韩人妻精品久久| 国产精品无码久久久久| 少妇撒尿一区二区在线视频| 中文字幕结果国产精品| 韩国精品久久久久久无码| 少妇熟女天堂网av|