婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > golang使用grpc+go-kit模擬oauth認證的操作

golang使用grpc+go-kit模擬oauth認證的操作

熱門標簽:壽光微信地圖標注 阿克蘇地圖標注 外呼系統用什么卡 涿州代理外呼系統 百度地圖標注后傳給手機 電話機器人軟件免費 外呼系統顯本地手機號 評價高的400電話辦理 excel地圖標注分布數據

我們使用grpc對外的接口,進行服務,模擬對外認證的接口

首先我們要了解oauth的基本認證過程

第三方的服務端,在oauth2.0中作為一個客戶端的身份,進行請求數據。

用戶進行選擇第三方的登陸,比如選擇到某一個第三方的平臺進行登陸,則會跳轉到第三方登陸平臺

用戶輸入用戶名密碼,在第三方平臺進行登陸,,如果登陸成功,則返回code。

客戶端,也就是我們想要登陸的網站,將會讀取code,并且將會攜帶這個code,和第三方網站所頒發的密碼,進行請求token,如果code和注冊時所得到的密碼,都驗證成功,此時,第三方客戶端會返回一個token。

我們登陸的網站會攜帶這個token去請求用戶身份資源的服務器,如果token比對成功,則返回用戶的信息所以我們需要一些服務

codeserver,作用,分發code,驗證code的準確性

tokenserver,作用分發token,驗證token的準確性

loginserver,作用,登陸成功后,調用codeserver得到code

userdetailserver,作用調用tokenserver的token驗證,驗證token是否合法,如果合法,進行返回用戶的基本信息繼續,我們大概看一下這些功能具體怎樣實現。

實現

codeserver

type Codeserver struc (
	GetCode ()
	ValidCode ()
)
//函數的具體傳參今不寫了

其實我們的code和token,主要是使用redis數據庫進行實現,并且給申請的code和token設置過期時間, 也就是說,在數據庫中實現一個定時的作用,如果,申請完code,長時間不申請token則這個code會過期,就會讓用戶重新進行登陸,重新獲取code

func (s ServicesA) GetCode(c context.Context, req *codeserver.GetCodeReuqest) (*codeserver.RCodeResponse, error) {
	con , err := UseRedis()//加載redis,用于操作redis
	if err != nil {
		return nil , errors.New("the redis databases is not work")
	}
	randstr :=  GetRandomString(10)//隨機生成一個字符串作為code
	_ , err = con.Do("hset" , req.UserId , "code" , randstr)//插入數據庫,用于獲取token時進行驗證
	con.Do("set" , randstr , req.UserId , "EX" , 120)
	con.Do("EXPIRE" , req.UserId , 20)//設置code的過期時間
	if err != nil {
		return nil , errors.New("data is not insert")
	}
	return codeserver.RCodeResponse{Code: randstr} , nil
}
//檢查code是否合法
func (s ServicesA) Isvalid(c context.Context, req *codeserver.ValidRequest) (*codeserver.ValidResponse, error) {
	con , err := UseRedis()//加載redis
	if err != nil {
		return nil , errors.New("the databses is not work")
	}
	r , err := con.Do("get" , req.Code)//找到code,如果能找到code,則合法,找不到則不合法
	if err != nil {
		return nil , err
	}
	if r == nil {
		return codeserver.ValidResponse{IsValid: false} , nil
	} else {
		return codeserver.ValidResponse{IsValid: true} , nil
	}
}

至于其他的endpoint層和transport層等等,就先不寫了,我們就這篇文章主要是看怎樣模擬實現oauth

tokenserver

func Isvalid (request *codeserver.ValidRequest) bool {
	lis , err := grpc.Dial("127.0.0.1:8081" , grpc.WithInsecure())
	if err != nil {
		log.Println(err)
		return false
	}
	client := codeserver.NewCodeServerClient(lis)
	rep , err := client.Isvalid(context.Background() , request)
	if err != nil {
		log.Println(err)
		return false
	}
	if rep.IsValid {
		return true
	} else {
		return false
	}
}
func (s ServiceAI) GetToken(ctx context.Context, req *tokenservice.ReqGetToken) (*tokenservice.RepGetToken, error) {
//判斷code是否合法
	if !Isvalid(codeserver.ValidRequest{UserId: req.UserId , Code: req.Code}) {
		return nil , errors.New("code is not valid ")
	}
	con , err := UseRedis()
	if err != nil {
		return nil , errors.New("connet database default")
	}
	//通過code獲取clientid
	User := GetUserId(req.Code)
	mysql , err := UseMysql()
	if err != nil {
		log.Println("get secrete default")
	}
	var c Client
	mysql.Table("client").Where("id = ?",req.ClientId).Find(c)
//在mysql數據庫中進行查找,請求所攜帶的密碼,是否與第三方注冊時給的密碼是否相同,如果不相同,則不返回token。
	if c.Secret !=req.Secret {
		fmt.Println(c.Secret , " " , req.Secret)
		return nil , errors.New("not pi pei")
	}
	str := GetRandomString(11)
	_ , err = con.Do("hset" , User , "token" ,  str)
	con.Do("EXPIRE" , User , 120)
	//將生成的token進行插入數據庫,并設置過期時間,如果避免token被多次利用
	con.Do("set" , str , User , "EX" , 120)
	//設置userid和token的對應關系,避免沒有對應上,客戶端拿到token之后隨便拿取其他人的用戶濾數據
	if err != nil {
		return nil , err
	}
	return tokenservice.RepGetToken{Toen: str} , nil
}
//判斷token是都合法,給userdetailserver用,當服務器接到token后,需要調用這個接口,查看token是否合法,如果合法返回用戶數據
func (s ServiceAI) IsValidToken(ctx context.Context, req *tokenservice.IsValidTokenReq) (*tokenservice.IsValidToeknRep, error) {
	con , err := UseRedis()
	if err != nil {
		log.Println(err)
		return nil , err
	}
	r , err := con.Do("get" ,req.Token)
	if err != nil {
		return nil , err
	}
	if r == nil {
		return tokenservice.IsValidToeknRep{IsValid: false} , nil
	}
	rep := string(r.([]uint8))
	return tokenservice.IsValidToeknRep{IsValid: true , Userid: rep} , nil
}

useroauthserver

type User struct {
	Id int
	Name string
	Password string
	Al string
	UId string
}
func usemysql () (*gorm.DB , error) {
	return gorm.Open("mysql" , "root:123456@/oauth?charset=utf8parseTime=Trueloc=Local")
}
//調用codeserver接口,進行拿取code
func getcode (userid string) string {
	con , err := grpc.Dial(":8081" , grpc.WithInsecure())
	if err != nil {
		log.Println(err , errors.New("get code default"))
	}
	client := codeserver.NewCodeServerClient(con)
	rep , err := client.GetCode(context.Background() , codeserver.GetCodeReuqest{UserId: userid})
	if err != nil || rep == nil{
		log.Println(err)
		return ""
	}
	return rep.Code
}
//認證用戶,將上傳的用戶名和密碼進行比對。
func (a AuthServicesA) AuthT(ctx context.Context, req *userauth.AuthRequest) (*userauth.AuthResponse, error) {
	con , err := usemysql()
	if err != nil {
		log.Println(err)
		return nil , errors.New("the database is connect default")
	}
	var u User
	con.Table("user").Where("uid =?" , req.Id).Find(u)
	//在數據庫中進行查找,如果沒找到該用戶,說明該用戶不存在,或者用戶輸入錯誤
	if u == nil {
		return nil , errors.New("the id is wrong ")
	}
	if req.Password != u.Password {
		return nil , errors.New("the user password is wrong")
	}
//如果認證成功,則進行調用codeserver接口,返回code
	code :=getcode(req.Id)
	if code == "" {
		return userauth.AuthResponse{IsTrue: false} , nil
	}
	return userauth.AuthResponse{Code: code , IsTrue: true} , nil
}

基本原理就是這樣,但是我們還是差一個userdetail的服務端

這個服務端,主要作用就是拿到請求的token,并進行檢驗,如果檢驗成功,返回用戶數據,至于怎樣檢驗,就是調用tokenserver中的檢驗接口。

這里就不寫了,留給讀者完成。

我寫的這三個接口在gitee上有源碼,是基于golang寫的,使用的框架有grpc,go-kit的服務框架。

具體地址gitee.com/silves-xiang

補充:go-kit實踐之2:go-kit 實現注冊發現與負載均衡

一、介紹

grpc提供了簡單的負載均衡,需要自己實現服務發現resolve。我們既然要使用go-kit來治理微服務,那么我們就使用go-kit的注冊發現、負載均衡機制。

go-kit官方【stringsvc3】例子中使用的負載均衡方案是通過服務端轉發進行,翻找下源碼go-kit的服務注冊發現、負載均衡在【sd】包中。下面我們介紹怎么通過go-kit進行客戶端負載均衡。

go-kit提供的注冊中心

1、 etcd

2、 consul

3、 eureka

4、 zookeeper

go-kit提供的負載均衡

1、 random[隨機]

2、 roundRobin[輪詢]

只需實現Balancer接口,我們可以很容易的增加其它負載均衡機制

type Balancer interface {  
   Endpoint() (endpoint.Endpoint, error)  
}

etcd注冊發現

etcd和zookeeper類似是一個高可用、強一致性的存儲倉庫,擁有服務發現功能。 我們就通過go-kit提供的etcd包來實現服務注冊發現

二、示例

1、protobuf文件及生成對應的go文件

syntax = "proto3";
 
// 請求書詳情的參數結構  book_id 32位整形
message BookInfoParams {
    int32 book_id = 1;
} 
 
// 書詳情信息的結構   book_name字符串類型
message BookInfo {
    int32 book_id = 1;
    string  book_name = 2;
}
 
// 請求書列表的參數結構  page、limit   32位整形
message BookListParams {
    int32 page = 1;
    int32 limit = 2;
}
  
// 書列表的結構    BookInfo結構數組
message BookList {
    repeated BookInfo book_list = 1;
}
// 定義 獲取書詳情  和 書列表服務   入參出參分別為上面所定義的結構
service BookService {
    rpc GetBookInfo (BookInfoParams) returns (BookInfo) {}
    rpc GetBookList (BookListParams) returns (BookList) {}
}

生成對應的go語言代碼文件:protoc --go_out=plugins=grpc:. book.proto (其中:protobuf文件名為:book.proto)

2、Server端代碼

package main 
import (
	"MyKit"
	"context"
	"fmt"
	"github.com/go-kit/kit/endpoint"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/sd/etcdv3"
	grpc_transport "github.com/go-kit/kit/transport/grpc"
	"google.golang.org/grpc"
	"net"
	"time"
)
 
type BookServer struct {
	bookListHandler grpc_transport.Handler
	bookInfoHandler grpc_transport.Handler
}
 
//一下兩個方法實現了 protoc生成go文件對應的接口:
/*
// BookServiceServer is the server API for BookService service.
type BookServiceServer interface {
	GetBookInfo(context.Context, *BookInfoParams) (*BookInfo, error)
	GetBookList(context.Context, *BookListParams) (*BookList, error)
}
*/
//通過grpc調用GetBookInfo時,GetBookInfo只做數據透傳, 調用BookServer中對應Handler.ServeGRPC轉交給go-kit處理
func (s *BookServer) GetBookInfo(ctx context.Context, in *book.BookInfoParams) (*book.BookInfo, error) {
 
	_, rsp, err := s.bookInfoHandler.ServeGRPC(ctx, in)
	if err != nil {
		return nil, err
 
	}
	/*
	if info,ok:=rsp.(*book.BookInfo);ok {
		return info,nil
	}
	return nil,errors.New("rsp.(*book.BookInfo)斷言出錯")
	*/
	return rsp.(*book.BookInfo), err //直接返回斷言的結果
}
 
//通過grpc調用GetBookList時,GetBookList只做數據透傳, 調用BookServer中對應Handler.ServeGRPC轉交給go-kit處理
func (s *BookServer) GetBookList(ctx context.Context, in *book.BookListParams) (*book.BookList, error) {
	_, rsp, err := s.bookListHandler.ServeGRPC(ctx, in)
	if err != nil {
		return nil, err
	}
	return rsp.(*book.BookList), err
}
 
//創建bookList的EndPoint
func makeGetBookListEndpoint()endpoint.Endpoint  {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		b:=new(book.BookList)
		b.BookList=append(b.BookList,book.BookInfo{BookId:1,BookName:"Go語言入門到精通"})
		b.BookList=append(b.BookList,book.BookInfo{BookId:2,BookName:"微服務入門到精通"})
		b.BookList=append(b.BookList,book.BookInfo{BookId:2,BookName:"區塊鏈入門到精通"})
		return b,nil
	}
}
 
//創建bookInfo的EndPoint
func makeGetBookInfoEndpoint() endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		//請求詳情時返回 書籍信息
		req := request.(*book.BookInfoParams)
		b := new(book.BookInfo)
		b.BookId = req.BookId
		b.BookName = "Go入門到精通"
		return b, nil
	}
}
 
func decodeRequest(_ context.Context, req interface{}) (interface{}, error) {
	return req, nil
}
 
func encodeResponse(_ context.Context, rsp interface{}) (interface{}, error) {
	return rsp, nil
}
 
func main() {
	var (
		etcdServer     = "127.0.0.1:2379"        //etcd服務的IP地址
		prefix         = "/services/book/"       //服務的目錄
		ServerInstance = "127.0.0.1:50052"       //當前實例Server的地址
		key            = prefix + ServerInstance //服務實例注冊的路徑
		value          = ServerInstance
		ctx            = context.Background()
		//服務監聽地址
		serviceAddress = ":50052"
	)
	//etcd連接參數
	option := etcdv3.ClientOptions{DialTimeout: time.Second * 3, DialKeepAlive: time.Second * 3}
	//創建連接
	client, err := etcdv3.NewClient(ctx, []string{etcdServer}, option)
	if err != nil {
		panic(err)
	}
	//創建注冊
	registrar := etcdv3.NewRegistrar(client, etcdv3.Service{Key: key, Value: value}, log.NewNopLogger())
	registrar.Register() //啟動注冊服務
	bookServer := new(BookServer)
	bookListHandler := grpc_transport.NewServer(
		makeGetBookListEndpoint(),
		decodeRequest,
		encodeResponse,
	)
	bookServer.bookListHandler = bookListHandler
 
	bookInfoHandler := grpc_transport.NewServer(
		makeGetBookInfoEndpoint(),
		decodeRequest,
		encodeResponse,
	)
	bookServer.bookInfoHandler = bookInfoHandler
 
	listener, err := net.Listen("tcp", serviceAddress) //網絡監聽,注意對應的包為:"net"
	if err != nil {
		fmt.Println(err)
		return
	}
	gs := grpc.NewServer(grpc.UnaryInterceptor(grpc_transport.Interceptor))
	book.RegisterBookServiceServer(gs, bookServer) //調用protoc生成的代碼對應的注冊方法
	gs.Serve(listener)                             //啟動Server
 
}

3、Client端代碼

package main 
import (
	"MyKit"
	"context"
	"fmt"
	"github.com/go-kit/kit/endpoint"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/sd"
	"github.com/go-kit/kit/sd/etcdv3"
	"github.com/go-kit/kit/sd/lb"
	"google.golang.org/grpc"
	"io"
	"time"
)
 
func main() {
 
	var (
		//注冊中心地址
		etcdServer = "127.0.0.1:2379"
		//監聽的服務前綴
		prefix = "/services/book/"
		ctx    = context.Background()
	)
	options := etcdv3.ClientOptions{
		DialTimeout:   time.Second * 3,
		DialKeepAlive: time.Second * 3,
	}
	//連接注冊中心
	client, err := etcdv3.NewClient(ctx, []string{etcdServer}, options)
	if err != nil {
		panic(err)
	}
	logger := log.NewNopLogger()
	//創建實例管理器, 此管理器會Watch監聽etc中prefix的目錄變化更新緩存的服務實例數據
	instancer, err := etcdv3.NewInstancer(client, prefix, logger)
	if err != nil {
		panic(err)
	}
	//創建端點管理器, 此管理器根據Factory和監聽的到實例創建endPoint并訂閱instancer的變化動態更新Factory創建的endPoint
	endpointer := sd.NewEndpointer(instancer, reqFactory, logger) //reqFactory自定義的函數,主要用于端點層(endpoint)接受并顯示數據
	//創建負載均衡器
	balancer := lb.NewRoundRobin(endpointer)
 
	/**
	我們可以通過負載均衡器直接獲取請求的endPoint,發起請求
	reqEndPoint,_ := balancer.Endpoint()
	*/
 
	/**
	也可以通過retry定義嘗試次數進行請求
	*/
	reqEndPoint := lb.Retry(3, 3*time.Second, balancer)
 
	//現在我們可以通過 endPoint 發起請求了
	req := struct{}{}
	if _, err = reqEndPoint(ctx, req); err != nil {
		panic(err)
	}
}
 
//通過傳入的 實例地址  創建對應的請求endPoint
func reqFactory(instanceAddr string) (endpoint.Endpoint, io.Closer, error) {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		fmt.Println("請求服務: ", instanceAddr)
		conn, err := grpc.Dial(instanceAddr, grpc.WithInsecure())
		if err != nil {
			fmt.Println(err)
			panic("connect error")
		}
		defer conn.Close()
		bookClient := book.NewBookServiceClient(conn)
		bi, _ := bookClient.GetBookInfo(context.Background(), book.BookInfoParams{BookId: 1})
		fmt.Println("獲取書籍詳情")
		fmt.Println("bookId: 1", " => ", "bookName:", bi.BookName)
 
		bl, _ := bookClient.GetBookList(context.Background(), book.BookListParams{Page: 1, Limit: 10})
		fmt.Println("獲取書籍列表")
		for _, b := range bl.BookList {
			fmt.Println("bookId:", b.BookId, " => ", "bookName:", b.BookName)
		}
		return nil, nil
	}, nil, nil
}

4、運行

(1)安裝etcd并啟動

由于本實例服務發現采用了etcd,因此在運行之前需要先安裝etcd并運行。

(2)etcd是一個分布式一致性鍵值存儲,其主要用于分布式系統的共享配置和服務發現。etcd由Go語言編寫.

下載地址: https://github.com/coreos/etcd/releases

將壓縮文件解壓到指定文件夾,解壓后的目錄如下:

其中etcd.exe是服務端,etcdctl.exe是客戶端。點擊etcd.exe運行etcd服務。(注:設置環境變量自由決定,此實例也可以不用設置)

(2)實例運行

先運行Server端,在運行Client端,效果如下:

5、問題匯總

如果運行時,提示一下錯誤:

panic: /debug/requests is already registered. You may have two independent copies of golang.org/x/net/trace in your binary, trying to maintain separate state. This may involve a vendored copy of golang.org/
x/net/trace.
 
goroutine 1 [running]:
go.etcd.io/etcd/vendor/golang.org/x/net/trace.init.0()
        D:/GoSrc/src/go.etcd.io/etcd/vendor/golang.org/x/net/trace/trace.go:116 +0x1ab
exit status 2

說明golang.org/x/net/包下的 trace 與go.etcd.io/etcd/vendor/golang.org/x/net/ 包下trace有沖突,解決方法:找到go.etcd.io\etcd\vendor目錄:

由于已經在src目錄下存在golang.org 與google.golang.org兩個包

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

您可能感興趣的文章:
  • 基于golang中container/list包的用法說明
  • Golang中List的實現方法示例詳解
  • golang中for range的取地址操作陷阱介紹
  • golang如何去除多余空白字符(含制表符)
  • 用golang如何替換某個文件中的字符串
  • golang正則之命名分組方式
  • 解決golang中container/list包中的坑

標簽:欽州 雞西 重慶 汕頭 蘭州 梅河口 吐魯番 銅川

巨人網絡通訊聲明:本文標題《golang使用grpc+go-kit模擬oauth認證的操作》,本文關鍵詞  golang,使用,grpc+go-kit,模擬,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《golang使用grpc+go-kit模擬oauth認證的操作》相關的同類信息!
  • 本頁收集關于golang使用grpc+go-kit模擬oauth認證的操作的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    337p日本欧洲亚洲大胆色噜噜| 51精品秘密在线观看| 欧美大度的电影原声| 91在线观看地址| 国产精品资源在线看| 亚洲h在线观看| 欧美国产1区2区| 91在线视频免费观看| 极品少妇xxxx偷拍精品少妇| 日韩不卡免费视频| 日韩在线一二三区| 性欧美大战久久久久久久久| 一区二区激情视频| 一区二区三区不卡视频| 亚洲激情第一区| 亚洲午夜精品网| 亚洲成人免费电影| 视频一区二区不卡| 免费人成精品欧美精品 | 精品综合免费视频观看| 日韩在线播放一区二区| 午夜精品福利视频网站| 亚洲va中文字幕| 婷婷一区二区三区| 调教+趴+乳夹+国产+精品| 亚洲精品免费在线观看| 亚洲欧洲日韩av| 综合av第一页| 亚洲一区二区在线视频| 亚洲成人av电影| 免费在线观看成人| 韩国欧美国产1区| 粉嫩欧美一区二区三区高清影视| 成人午夜电影网站| 一本大道av一区二区在线播放| 亚洲精品国产无套在线观| 首页国产丝袜综合| 天天av天天翘天天综合网| 亚洲欧美在线高清| 成人毛片视频在线观看| 精品久久久久久无| 8x8x8国产精品| 亚洲综合在线免费观看| 国产精品一区一区三区| 国产日韩欧美麻豆| 亚洲欧美日韩系列| 99久久久免费精品国产一区二区| 欧美成人女星排行榜| 成人一级片在线观看| 国产欧美久久久精品影院| 不卡免费追剧大全电视剧网站| 久久九九久精品国产免费直播| 久久国产乱子精品免费女| 精品伦理精品一区| 99久久99久久综合| 精品一区二区在线看| 香蕉久久夜色精品国产使用方法 | 亚洲一区二区视频| 亚洲欧美日本在线| 亚洲男人都懂的| 精品国产乱码久久久久久久久| 亚洲尤物在线视频观看| 成人黄色软件下载| 51午夜精品国产| 亚洲第一二三四区| 三级成人在线视频| 亚洲一区在线视频观看| 狠狠网亚洲精品| 色欲综合视频天天天| 欧美久久久久久久久久| av在线播放不卡| 亚洲亚洲精品在线观看| 欧美体内she精高潮| 欧美系列在线观看| 精品日韩一区二区三区免费视频| 婷婷久久综合九色综合绿巨人| 欧美α欧美αv大片| 99国内精品久久| 不卡的电影网站| 亚洲成人自拍网| 综合激情网...| 精品视频色一区| 成人不卡免费av| 精品一区二区三区在线播放视频 | 亚洲一区免费在线观看| 久久久www免费人成精品| 欧美中文字幕一区| 精品亚洲免费视频| 亚洲一卡二卡三卡四卡五卡| 精品捆绑美女sm三区| 91久久精品网| 成人av在线看| 国产一区二区不卡在线 | 视频一区二区欧美| 污片在线观看一区二区| 亚洲欧洲韩国日本视频| 中文字幕一区二| 国产精品久久看| 国产精品久久久99| 欧美国产欧美亚州国产日韩mv天天看完整| 成人av综合一区| 国产精品888| 久久99精品久久只有精品| 一区二区三区四区不卡在线| 国产精品亲子伦对白| 亚洲综合自拍偷拍| 丝袜亚洲另类欧美综合| 免费成人在线网站| 色先锋资源久久综合| 色94色欧美sute亚洲线路一久| 欧美揉bbbbb揉bbbbb| 久久色.com| 日韩精品欧美成人高清一区二区| 久久国产夜色精品鲁鲁99| 成人精品国产福利| 久久久久久综合| 亚洲欧美激情视频在线观看一区二区三区| 亚洲欧洲国产日本综合| 另类综合日韩欧美亚洲| 成人午夜精品在线| 欧美xxx久久| 久久精品国产一区二区| 色综合一区二区| 亚洲特级片在线| 91首页免费视频| 国产精品色婷婷久久58| 精品一区二区三区在线播放视频| 欧美色国产精品| 中文在线一区二区| 激情五月婷婷综合网| 欧美一区二区播放| 强制捆绑调教一区二区| 欧美日韩国产高清一区二区三区 | 91精品国产综合久久久久久久久久 | 欧美哺乳videos| 亚洲国产精品久久久久婷婷884 | 色诱视频网站一区| 国产视频视频一区| 国产一区欧美一区| 欧美精品一区二区在线观看| 精品一区二区三区在线观看国产| 欧美日韩一区二区三区视频| 亚洲已满18点击进入久久| 欧美群妇大交群中文字幕| 久久精品二区亚洲w码| 国产精品久久久久久久久搜平片| av在线一区二区三区| 性欧美疯狂xxxxbbbb| 国产日本一区二区| 日韩一区二区三区av| 国产99久久久国产精品免费看| 国产精品美日韩| 7777精品伊人久久久大香线蕉最新版| 婷婷综合五月天| 亚洲视频网在线直播| 欧美xxxxxxxxx| 欧美在线看片a免费观看| 日本欧美在线观看| 亚洲人成网站精品片在线观看| 欧美电影免费观看高清完整版在 | 日韩毛片精品高清免费| 91精品麻豆日日躁夜夜躁| 97久久精品人人爽人人爽蜜臀| 亚洲资源在线观看| 亚洲一区二区在线观看视频| 亚洲一区在线免费观看| 久久不见久久见免费视频1| 99re成人在线| 欧美喷潮久久久xxxxx| 欧美高清视频www夜色资源网| 欧美日产国产精品| 日本一区二区三区在线不卡| 亚洲欧美日本在线| 日韩精品一二三四| 久久狠狠亚洲综合| 国产一区二区主播在线| 国产精品69毛片高清亚洲| 99久久久久免费精品国产| 欧美电影免费观看高清完整版 | 一区二区三区成人| 久久精品夜色噜噜亚洲aⅴ| 国产精品美女视频| 一区二区三区毛片| 国产在线播放一区二区三区| 国产成人精品影院| 99久精品国产| 欧美精品乱码久久久久久| 国产日产欧美精品一区二区三区| 国产精品萝li| 国产一区二区三区免费在线观看 | 亚洲一区成人在线| 国产激情一区二区三区桃花岛亚洲| 夫妻av一区二区| 欧美性猛交xxxx黑人交| 国产精品污网站| 蜜桃久久精品一区二区| 色婷婷激情综合| 国产肉丝袜一区二区| 免费在线观看一区| 欧美日韩中文国产|