日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

harbor登录验证_Harbor 源码浅析

發(fā)布時(shí)間:2024/9/27 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 harbor登录验证_Harbor 源码浅析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Harbor 源碼淺析?www.qikqiak.com

Harbor 是一個(gè)CNCF基金會(huì)托管的開源的可信的云原生docker registry項(xiàng)目,可以用于存儲(chǔ)、簽名、掃描鏡像內(nèi)容,Harbor 通過添加一些常用的功能如安全性、身份權(quán)限管理等來擴(kuò)展 docker registry 項(xiàng)目,此外還支持在 registry 之間復(fù)制鏡像,還提供更加高級(jí)的安全功能,如用戶管理、訪問控制和活動(dòng)審計(jì)等,在新版本中還添加了Helm倉庫托管的支持。

本文所有源碼基于 Harbor release-1.7.0 版本進(jìn)行分析。

Harbor最核心的功能就是給 docker registry 添加上一層權(quán)限保護(hù)的功能,要實(shí)現(xiàn)這個(gè)功能,就需要我們?cè)谑褂?docker login、pull、push 等命令的時(shí)候進(jìn)行攔截,先進(jìn)行一些權(quán)限相關(guān)的校驗(yàn),再進(jìn)行操作,其實(shí)這一系列的操作 docker registry v2 就已經(jīng)為我們提供了支持,v2 集成了一個(gè)安全認(rèn)證的功能,將安全認(rèn)證暴露給外部服務(wù),讓外部服務(wù)去實(shí)現(xiàn)。

docker registry v2 認(rèn)證

上面我們說了 docker registry v2 將安全認(rèn)證暴露給了外部服務(wù)使用,那么是怎樣暴露的呢?我們?cè)诿钚兄休斎雂ocker login https://registry.qikqiak.com為例來為大家說明下認(rèn)證流程:

  • 1. docker client 接收到用戶輸入的 docker login 命令,將命令轉(zhuǎn)化為調(diào)用 engine api 的 RegistryLogin 方法
  • 2. 在 RegistryLogin 方法中通過 http 盜用 registry 服務(wù)中的 auth 方法
  • 3. 因?yàn)槲覀冞@里使用的是 v2 版本的服務(wù),所以會(huì)調(diào)用 loginV2 方法,在 loginV2 方法中會(huì)進(jìn)行 /v2/ 接口調(diào)用,該接口會(huì)對(duì)請(qǐng)求進(jìn)行認(rèn)證
  • 4. 此時(shí)的請(qǐng)求中并沒有包含 token 信息,認(rèn)證會(huì)失敗,返回 401 錯(cuò)誤,同時(shí)會(huì)在 header 中返回去哪里請(qǐng)求認(rèn)證的服務(wù)器地址
  • 5. registry client 端收到上面的返回結(jié)果后,便會(huì)去返回的認(rèn)證服務(wù)器那里進(jìn)行認(rèn)證請(qǐng)求,向認(rèn)證服務(wù)器發(fā)送的請(qǐng)求的 header 中包含有加密的用戶名和密碼
  • 6. 認(rèn)證服務(wù)器從 header 中獲取到加密的用戶名和密碼,這個(gè)時(shí)候就可以結(jié)合實(shí)際的認(rèn)證系統(tǒng)進(jìn)行認(rèn)證了,比如從數(shù)據(jù)庫中查詢用戶認(rèn)證信息或者對(duì)接 ldap 服務(wù)進(jìn)行認(rèn)證校驗(yàn)
  • 7. 認(rèn)證成功后,會(huì)返回一個(gè) token 信息,client 端會(huì)拿著返回的 token 再次向 registry 服務(wù)發(fā)送請(qǐng)求,這次需要帶上得到的 token,請(qǐng)求驗(yàn)證成功,返回狀態(tài)碼就是200了
  • 8. docker client 端接收到返回的200狀態(tài)碼,說明操作成功,在控制臺(tái)上打印Login Succeeded的信息

至此,整個(gè)登錄過程完成,整個(gè)過程可以用下面的流程圖來說明:

要完成上面的登錄認(rèn)證過程有兩個(gè)關(guān)鍵點(diǎn)需要注意:怎樣讓 registry 服務(wù)知道服務(wù)認(rèn)證地址?我們自己提供的認(rèn)證服務(wù)生成的 token 為什么 registry 就能夠識(shí)別?

對(duì)于第一個(gè)問題,比較好解決,registry 服務(wù)本身就提供了一個(gè)配置文件,可以在啟動(dòng) registry 服務(wù)的配置文件中指定上認(rèn)證服務(wù)地址即可,其中有如下這樣的一段配置信息:

...... auth:token:realm: token-realmservice: token-serviceissuer: registry-token-issuerrootcertbundle: /root/certs/bundle ......

其中 realm 就可以用來指定一個(gè)認(rèn)證服務(wù)的地址,下面我們可以看到 Harbor 中該配置的內(nèi)容

關(guān)于 registry 的配置,可以參考官方文檔:https://docs.docker.com/registry/configuration/

第二個(gè)問題,就是 registry 怎么能夠識(shí)別我們返回的 token 文件?如果按照 registry 的要求生成一個(gè) token,是不是 registry 就可以識(shí)別了?所以我們需要在我們的認(rèn)證服務(wù)器中按照 registry 的要求生成 token,而不是隨便亂生成。那么要怎么生成呢?我們可以在 docker registry 的源碼中可以看到 token 是如何定義的,文件路徑在distribution/registry/token/token.go,從源碼中我們可以看到 token 是通過JWT(JSON Web Token)來實(shí)現(xiàn)的,所以我們按照要求生成一個(gè) JWT 的 token 就可以了。

Harbor 認(rèn)證

上面我們已經(jīng)說明了 docker registry v2 認(rèn)證的整個(gè)流程,Harbor 實(shí)際上核心的功能就是提供上面的認(rèn)證服務(wù)的功能。我們?cè)?Harbor 的源碼目錄中可以查看到 registry 服務(wù)的配置文件,路徑為:make/common/templates/registry/config.yml,其中有兩個(gè)非常重要的配置信息:

...... auth:token:issuer: harbor-token-issuerrealm: $public_url/service/tokenrootcertbundle: /etc/registry/root.crtservice: harbor-registry ......

一個(gè)就是上面我們提到的 auth.token.realm,是用來提供 registry v2 安全認(rèn)證的外部服務(wù)地址,這里默認(rèn)的配置是$public_url/service/token,其中$public_url就是 Harbor 服務(wù)的主域地址,所以安全認(rèn)證服務(wù)就是去請(qǐng)求/service/token這個(gè)地址了,由于 Harbor 是基于 beego 這個(gè) web 框架進(jìn)行開發(fā)的,所以我們只需要去查找下/service/token這個(gè)路由,就可以找到對(duì)應(yīng)的請(qǐng)求處理方法了。可以很容易在文件src/core/router.go文件中找到改路由:

func initRouters() {......beego.Router("/service/token", &token.Handler{})...... }

上面的請(qǐng)求處理方法在src/core/service/token.go文件中,里面有一個(gè)Get方法就是用來處理該請(qǐng)求的:

func (h *Handler) Get() {request := h.Ctx.Requestlog.Debugf("URL for token request: %s", request.URL.String())service := h.GetString("service")tokenCreator, ok := creatorMap[service]if !ok {errMsg := fmt.Sprintf("Unable to handle service: %s", service)log.Errorf(errMsg)h.CustomAbort(http.StatusBadRequest, errMsg)}token, err := tokenCreator.Create(request)if err != nil {if _, ok := err.(*unauthorizedError); ok {h.CustomAbort(http.StatusUnauthorized, "")}log.Errorf("Unexpected error when creating the token, error: %v", err)h.CustomAbort(http.StatusInternalServerError, "")}h.Data["json"] = tokenh.ServeJSON()}

上面的方法通過參數(shù) service 來獲取一個(gè) tokenCreator,然后調(diào)用 Create 方法生成 token,方法如下:

func (g generalCreator) Create(r *http.Request) (*models.Token, error) {var err errorscopes := parseScopes(r.URL)log.Debugf("scopes: %v", scopes)ctx, err := filter.GetSecurityContext(r)if err != nil {return nil, fmt.Errorf("failed to get security context from request")}pm, err := filter.GetProjectManager(r)if err != nil {return nil, fmt.Errorf("failed to get project manager from request")}// for docker loginif !ctx.IsAuthenticated() {if len(scopes) == 0 {return nil, &unauthorizedError{}}}access := GetResourceActions(scopes)err = filterAccess(access, ctx, pm, g.filterMap)if err != nil {return nil, err}return MakeToken(ctx.GetUsername(), g.service, access) }

這里就做了一系列的權(quán)限校驗(yàn),如果沒有問題就生成一個(gè) token 對(duì)象返回,這里生成的 Token 對(duì)象結(jié)構(gòu)體如下:

type Token struct {Token string `json:"token"`ExpiresIn int `json:"expires_in"`IssuedAt string `json:"issued_at"` }

和 JWT 定義的 token 格式是保持一致的,所以 docker registry v2 能夠識(shí)別我們返回的 token 字符串。

Harbor API

上面是 Harbor 提供的最核心的認(rèn)證服務(wù)功能,除此之外還有很多其他的功能,比如 Harbor 還提供了一個(gè)額外的 Dashboard 可供我們操作,還支持 Helm Chart 倉庫。同樣我們?cè)倏聪轮暗膕rc/core/router.go文件:

func initRouters() {// standaloneif !config.WithAdmiral() {// Controller API:beego.Router("/c/login", &controllers.CommonController{}, "post:Login")beego.Router("/c/log_out", &controllers.CommonController{}, "get:LogOut")beego.Router("/c/reset", &controllers.CommonController{}, "post:ResetPassword")beego.Router("/c/userExists", &controllers.CommonController{}, "post:UserExists")beego.Router("/c/sendEmail", &controllers.CommonController{}, "get:SendResetEmail")// API:beego.Router("/api/projects/:pid([0-9]+)/members/?:pmid([0-9]+)", &api.ProjectMemberAPI{})beego.Router("/api/projects/", &api.ProjectAPI{}, "head:Head")beego.Router("/api/projects/:id([0-9]+)", &api.ProjectAPI{})beego.Router("/api/users/:id", &api.UserAPI{}, "get:Get;delete:Delete;put:Put")beego.Router("/api/users", &api.UserAPI{}, "get:List;post:Post")beego.Router("/api/users/:id([0-9]+)/password", &api.UserAPI{}, "put:ChangePassword")beego.Router("/api/users/:id/sysadmin", &api.UserAPI{}, "put:ToggleUserAdminRole")beego.Router("/api/usergroups/?:ugid([0-9]+)", &api.UserGroupAPI{})beego.Router("/api/ldap/ping", &api.LdapAPI{}, "post:Ping")beego.Router("/api/ldap/users/search", &api.LdapAPI{}, "get:Search")beego.Router("/api/ldap/groups/search", &api.LdapAPI{}, "get:SearchGroup")beego.Router("/api/ldap/users/import", &api.LdapAPI{}, "post:ImportUser")beego.Router("/api/email/ping", &api.EmailAPI{}, "post:Ping")}// APIbeego.Router("/api/ping", &api.SystemInfoAPI{}, "get:Ping")beego.Router("/api/search", &api.SearchAPI{})beego.Router("/api/projects/", &api.ProjectAPI{}, "get:List;post:Post")beego.Router("/api/projects/:id([0-9]+)/logs", &api.ProjectAPI{}, "get:Logs")beego.Router("/api/projects/:id([0-9]+)/_deletable", &api.ProjectAPI{}, "get:Deletable")beego.Router("/api/projects/:id([0-9]+)/metadatas/?:name", &api.MetadataAPI{}, "get:Get")beego.Router("/api/projects/:id([0-9]+)/metadatas/", &api.MetadataAPI{}, "post:Post")beego.Router("/api/projects/:id([0-9]+)/metadatas/:name", &api.MetadataAPI{}, "put:Put;delete:Delete")beego.Router("/api/repositories", &api.RepositoryAPI{}, "get:Get")beego.Router("/api/repositories/scanAll", &api.RepositoryAPI{}, "post:ScanAll")beego.Router("/api/repositories/*", &api.RepositoryAPI{}, "delete:Delete;put:Put")beego.Router("/api/repositories/*/labels", &api.RepositoryLabelAPI{}, "get:GetOfRepository;post:AddToRepository")beego.Router("/api/repositories/*/labels/:id([0-9]+)", &api.RepositoryLabelAPI{}, "delete:RemoveFromRepository")beego.Router("/api/repositories/*/tags/:tag", &api.RepositoryAPI{}, "delete:Delete;get:GetTag")beego.Router("/api/repositories/*/tags/:tag/labels", &api.RepositoryLabelAPI{}, "get:GetOfImage;post:AddToImage")beego.Router("/api/repositories/*/tags/:tag/labels/:id([0-9]+)", &api.RepositoryLabelAPI{}, "delete:RemoveFromImage")beego.Router("/api/repositories/*/tags", &api.RepositoryAPI{}, "get:GetTags;post:Retag")beego.Router("/api/repositories/*/tags/:tag/scan", &api.RepositoryAPI{}, "post:ScanImage")beego.Router("/api/repositories/*/tags/:tag/vulnerability/details", &api.RepositoryAPI{}, "Get:VulnerabilityDetails")beego.Router("/api/repositories/*/tags/:tag/manifest", &api.RepositoryAPI{}, "get:GetManifests")beego.Router("/api/repositories/*/signatures", &api.RepositoryAPI{}, "get:GetSignatures")beego.Router("/api/repositories/top", &api.RepositoryAPI{}, "get:GetTopRepos")beego.Router("/api/jobs/replication/", &api.RepJobAPI{}, "get:List;put:StopJobs")beego.Router("/api/jobs/replication/:id([0-9]+)", &api.RepJobAPI{})beego.Router("/api/jobs/replication/:id([0-9]+)/log", &api.RepJobAPI{}, "get:GetLog")beego.Router("/api/jobs/scan/:id([0-9]+)/log", &api.ScanJobAPI{}, "get:GetLog")beego.Router("/api/system/gc", &api.GCAPI{}, "get:List")beego.Router("/api/system/gc/:id", &api.GCAPI{}, "get:GetGC")beego.Router("/api/system/gc/:id([0-9]+)/log", &api.GCAPI{}, "get:GetLog")beego.Router("/api/system/gc/schedule", &api.GCAPI{}, "get:Get;put:Put;post:Post")beego.Router("/api/policies/replication/:id([0-9]+)", &api.RepPolicyAPI{})beego.Router("/api/policies/replication", &api.RepPolicyAPI{}, "get:List")beego.Router("/api/policies/replication", &api.RepPolicyAPI{}, "post:Post")beego.Router("/api/targets/", &api.TargetAPI{}, "get:List")beego.Router("/api/targets/", &api.TargetAPI{}, "post:Post")beego.Router("/api/targets/:id([0-9]+)", &api.TargetAPI{})beego.Router("/api/targets/:id([0-9]+)/policies/", &api.TargetAPI{}, "get:ListPolicies")beego.Router("/api/targets/ping", &api.TargetAPI{}, "post:Ping")beego.Router("/api/logs", &api.LogAPI{})beego.Router("/api/configs", &api.ConfigAPI{}, "get:GetInternalConfig")beego.Router("/api/configurations", &api.ConfigAPI{})beego.Router("/api/configurations/reset", &api.ConfigAPI{}, "post:Reset")beego.Router("/api/statistics", &api.StatisticAPI{})beego.Router("/api/replications", &api.ReplicationAPI{})beego.Router("/api/labels", &api.LabelAPI{}, "post:Post;get:List")beego.Router("/api/labels/:id([0-9]+)", &api.LabelAPI{}, "get:Get;put:Put;delete:Delete")beego.Router("/api/labels/:id([0-9]+)/resources", &api.LabelAPI{}, "get:ListResources")beego.Router("/api/systeminfo", &api.SystemInfoAPI{}, "get:GetGeneralInfo")beego.Router("/api/systeminfo/volumes", &api.SystemInfoAPI{}, "get:GetVolumeInfo")beego.Router("/api/systeminfo/getcert", &api.SystemInfoAPI{}, "get:GetCert")beego.Router("/api/internal/syncregistry", &api.InternalAPI{}, "post:SyncRegistry")beego.Router("/api/internal/renameadmin", &api.InternalAPI{}, "post:RenameAdmin")beego.Router("/api/internal/configurations", &api.ConfigAPI{}, "get:GetInternalConfig")// external service that hosted on harbor process:beego.Router("/service/notifications", &registry.NotificationHandler{})beego.Router("/service/notifications/clair", &clair.Handler{}, "post:Handle")beego.Router("/service/notifications/jobs/scan/:id([0-9]+)", &jobs.Handler{}, "post:HandleScan")beego.Router("/service/notifications/jobs/replication/:id([0-9]+)", &jobs.Handler{}, "post:HandleReplication")beego.Router("/service/notifications/jobs/adminjob/:id([0-9]+)", &admin.Handler{}, "post:HandleAdminJob")beego.Router("/service/token", &token.Handler{})beego.Router("/v2/*", &controllers.RegistryProxy{}, "*:Handle")// APIs for chart repositoryif config.WithChartMuseum() {// Charts are controlled under projectschartRepositoryAPIType := &api.ChartRepositoryAPI{}beego.Router("/api/chartrepo/health", chartRepositoryAPIType, "get:GetHealthStatus")beego.Router("/api/chartrepo/:repo/charts", chartRepositoryAPIType, "get:ListCharts")beego.Router("/api/chartrepo/:repo/charts/:name", chartRepositoryAPIType, "get:ListChartVersions")beego.Router("/api/chartrepo/:repo/charts/:name", chartRepositoryAPIType, "delete:DeleteChart")beego.Router("/api/chartrepo/:repo/charts/:name/:version", chartRepositoryAPIType, "get:GetChartVersion")beego.Router("/api/chartrepo/:repo/charts/:name/:version", chartRepositoryAPIType, "delete:DeleteChartVersion")beego.Router("/api/chartrepo/:repo/charts", chartRepositoryAPIType, "post:UploadChartVersion")beego.Router("/api/chartrepo/:repo/prov", chartRepositoryAPIType, "post:UploadChartProvFile")beego.Router("/api/chartrepo/charts", chartRepositoryAPIType, "post:UploadChartVersion")// Repository servicesbeego.Router("/chartrepo/:repo/index.yaml", chartRepositoryAPIType, "get:GetIndexByRepo")beego.Router("/chartrepo/index.yaml", chartRepositoryAPIType, "get:GetIndex")beego.Router("/chartrepo/:repo/charts/:filename", chartRepositoryAPIType, "get:DownloadChart")// Labels for chartchartLabelAPIType := &api.ChartLabelAPI{}beego.Router("/api/chartrepo/:repo/charts/:name/:version/labels", chartLabelAPIType, "get:GetLabels;post:MarkLabel")beego.Router("/api/chartrepo/:repo/charts/:name/:version/labels/:id([0-9]+)", chartLabelAPIType, "delete:RemoveLabel")}// Error pagesbeego.ErrorController(&controllers.ErrorController{})}

上面這個(gè)文件里面就定義了 Harbor 核心的一些 API,其中如果!config.WithAdmiral()為真,則定義的一些用登錄相關(guān)接口就會(huì)生效,Admiral 是 Vmware 的一個(gè)容器管理平臺(tái),如果我們?cè)谂渲梦募卸x了參數(shù)admiral_url,那么 Harbor 就會(huì)和 Admiral 進(jìn)行交互,如果沒有配置這個(gè)參數(shù),那么就會(huì)去和我們定義的 login 相關(guān)接口進(jìn)行交互了。我們這里簡(jiǎn)單介紹一下主要的接口,第一個(gè)登錄接口post:Login:

// Login handles login request from UI. func (cc *CommonController) Login() {principal := cc.GetString("principal")password := cc.GetString("password")user, err := auth.Login(models.AuthModel{Principal: principal,Password: password,})if err != nil {log.Errorf("Error occurred in UserLogin: %v", err)cc.CustomAbort(http.StatusUnauthorized, "")}if user == nil {cc.CustomAbort(http.StatusUnauthorized, "")}cc.SetSession("user", *user) }

根據(jù)請(qǐng)求獲取用戶名和密碼,然后調(diào)用auth.Login方法進(jìn)行登錄校驗(yàn),方法位于文件src/core/auth/authenticator.go下:

// Login authenticates user credentials based on setting. func Login(m models.AuthModel) (*models.User, error) {authMode, err := config.AuthMode()if err != nil {return nil, err}if authMode == "" || dao.IsSuperUser(m.Principal) {authMode = common.DBAuth}log.Debug("Current AUTH_MODE is ", authMode)authenticator, ok := registry[authMode]if !ok {return nil, fmt.Errorf("Unrecognized auth_mode: %s", authMode)}if lock.IsLocked(m.Principal) {log.Debugf("%s is locked due to login failure, login failed", m.Principal)return nil, nil}user, err := authenticator.Authenticate(m)if err != nil {if _, ok = err.(ErrAuth); ok {log.Debugf("Login failed, locking %s, and sleep for %v", m.Principal, frozenTime)lock.Lock(m.Principal)time.Sleep(frozenTime)}return nil, err}err = authenticator.PostAuthenticate(user)return user, err }

通過authenticator.Authenticate方法進(jìn)行驗(yàn)證,這里就需要通過 authMode 來進(jìn)行判斷應(yīng)該調(diào)用哪個(gè)認(rèn)證方法 驗(yàn)證,該參數(shù)就是 Harbor 全局配置文件中的auth_mode參數(shù),默認(rèn)情況下auth_mode=db_auth,除此之外還可以設(shè)置成ldap_auth來通過提供一個(gè)LDAP Server進(jìn)行用戶認(rèn)證,也可以設(shè)置成uaa_auth來通過 cloud foundry 的 id manager 來進(jìn)行用戶認(rèn)證。比如如果使用數(shù)據(jù)庫驗(yàn)證的話,那么校驗(yàn)方法就在文件src/core/auth/db/db.go中,方法如下:

// Authenticate calls dao to authenticate user. func (d *Auth) Authenticate(m models.AuthModel) (*models.User, error) {u, err := dao.LoginByDb(m)if err != nil {return nil, err}if u == nil {return nil, auth.NewErrAuth("Invalid credentials")}return u, nil }

進(jìn)入LoginByDb方法,位于src/common/dao/user.go文件:

// LoginByDb is used for user to login with database auth mode. func LoginByDb(auth models.AuthModel) (*models.User, error) {o := GetOrmer()var users []models.Usern, err := o.Raw(`select * from harbor_user where (username = ? or email = ?) and deleted = false`,auth.Principal, auth.Principal).QueryRows(&users)if err != nil {return nil, err}if n == 0 {return nil, nil}user := users[0]if user.Password != utils.Encrypt(auth.Password, user.Salt) {return nil, nil}user.Password = "" // do not return the passwordreturn &user, nil }

上面這段代碼邏輯就很簡(jiǎn)單了,首先根據(jù)用戶名獲取用戶,然后將密碼加密進(jìn)行比較,驗(yàn)證通過就將 user 對(duì)象返回,并保存到 session 里面,這個(gè)后面會(huì)用到。

其它的 API 操作類似,在此不再一一講述,另外再和大家介紹一下鏡像倉庫的相關(guān) API 操作,鏡像操作相關(guān) API 主要位于/api/repositories下面,請(qǐng)求處理方法主要位于文件src/ui/api/repository.go中,比如獲取鏡像分頁列表數(shù)據(jù):

func (ra *RepositoryAPI) Get() {projectID, err := ra.GetInt64("project_id")if err != nil || projectID <= 0 {ra.HandleBadRequest(fmt.Sprintf("invalid project_id %s", ra.GetString("project_id")))return}labelID, err := ra.GetInt64("label_id", 0)if err != nil {ra.HandleBadRequest(fmt.Sprintf("invalid label_id: %s", ra.GetString("label_id")))return}exist, err := ra.ProjectMgr.Exists(projectID)if err != nil {ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %d",projectID), err)return}if !exist {ra.HandleNotFound(fmt.Sprintf("project %d not found", projectID))return}if !ra.SecurityCtx.HasReadPerm(projectID) {if !ra.SecurityCtx.IsAuthenticated() {ra.HandleUnauthorized()return}ra.HandleForbidden(ra.SecurityCtx.GetUsername())return}query := &models.RepositoryQuery{ProjectIDs: []int64{projectID},Name: ra.GetString("q"),LabelID: labelID,}query.Page, query.Size = ra.GetPaginationParams()query.Sort = ra.GetString("sort")total, err := dao.GetTotalOfRepositories(query)if err != nil {ra.HandleInternalServerError(fmt.Sprintf("failed to get total of repositories of project %d: %v",projectID, err))return}repositories, err := getRepositories(query)if err != nil {ra.HandleInternalServerError(fmt.Sprintf("failed to get repository: %v", err))return}ra.SetPaginationHeader(total, query.Page, query.Size)ra.Data["json"] = repositoriesra.ServeJSON() }

上面的邏輯也相對(duì)比較簡(jiǎn)單,獲取請(qǐng)求的參數(shù),拼湊成一個(gè) RepositoryQuery 對(duì)象,然后根據(jù)該對(duì)象去查詢倉庫列表數(shù)據(jù),并支持分頁返回,查詢只是就是簡(jiǎn)單的操作數(shù)據(jù)庫而已,其他操作也類似。不過我們仔細(xì)查看改文件中,并沒有提供創(chuàng)建倉庫的接口,這是因?yàn)閯?chuàng)建 Repository 是在上傳鏡像的時(shí)候創(chuàng)建的,這里又回到 registry 的配置文件,里面有一段如下的配置:

...... notifications:endpoints:- name: harbordisabled: falseurl: $core_url/service/notifications ......

其中配置的 url 就是倉庫的一個(gè)回調(diào) web hook 地址,在pull或者push鏡像后就會(huì)觸發(fā)該 hook 請(qǐng)求,比如 Harbor 這里就會(huì)去請(qǐng)求/service/notifications這個(gè) url:

// Post handles POST request, and records audit log or refreshes cache based on event. func (n *NotificationHandler) Post() {var notification models.Notificationerr := json.Unmarshal(n.Ctx.Input.CopyBody(1<<32), &notification)if err != nil {log.Errorf("failed to decode notification: %v", err)return}events, err := filterEvents(&notification)if err != nil {log.Errorf("failed to filter events: %v", err)return}for _, event := range events {repository := event.Target.Repositoryproject, _ := utils.ParseRepository(repository)tag := event.Target.Tagaction := event.Actionuser := event.Actor.Nameif len(user) == 0 {user = "anonymous"}pro, err := config.GlobalProjectMgr.Get(project)if err != nil {log.Errorf("failed to get project by name %s: %v", project, err)return}if pro == nil {log.Warningf("project %s not found", project)continue}go func() {if err := dao.AddAccessLog(models.AccessLog{Username: user,ProjectID: pro.ProjectID,RepoName: repository,RepoTag: tag,Operation: action,OpTime: time.Now(),}); err != nil {log.Errorf("failed to add access log: %v", err)}}()if action == "push" {go func() {exist := dao.RepositoryExists(repository)if exist {return}log.Debugf("Add repository %s into DB.", repository)repoRecord := models.RepoRecord{Name: repository,ProjectID: pro.ProjectID,}if err := dao.AddRepository(repoRecord); err != nil {log.Errorf("Error happens when adding repository: %v", err)}}()if !coreutils.WaitForManifestReady(repository, tag, 5) {log.Errorf("Manifest for image %s:%s is not ready, skip the follow up actions.", repository, tag)return}go func() {image := repository + ":" + tagerr := notifier.Publish(topic.ReplicationEventTopicOnPush, rep_notification.OnPushNotification{Image: image,})if err != nil {log.Errorf("failed to publish on push topic for resource %s: %v", image, err)return}log.Debugf("the on push topic for resource %s published", image)}()if autoScanEnabled(pro) {last, err := clairdao.GetLastUpdate()if err != nil {log.Errorf("Failed to get last update from Clair DB, error: %v, the auto scan will be skipped.", err)} else if last == 0 {log.Infof("The Vulnerability data is not ready in Clair DB, the auto scan will be skipped.", err)} else if err := coreutils.TriggerImageScan(repository, tag); err != nil {log.Warningf("Failed to scan image, repository: %s, tag: %s, error: %v", repository, tag, err)}}}if action == "pull" {go func() {log.Debugf("Increase the repository %s pull count.", repository)if err := dao.IncreasePullCount(repository); err != nil {log.Errorf("Error happens when increasing pull count: %v", repository)}}()}} }

從上面代碼中可以看到首先在 hook 中我們可以獲取到當(dāng)前操作的動(dòng)作,如果是 push 操作,首先判斷 repository 是否存在,如果不存在則創(chuàng)建,對(duì)于 pull 鏡像操作通過 IncreasePullCount 更新數(shù)據(jù)庫 pull 鏡像次數(shù):

// IncreasePullCount ... func IncreasePullCount(name string) (err error) {o := GetOrmer()num, err := o.QueryTable("repository").Filter("name", name).Update(orm.Params{"pull_count": orm.ColValue(orm.ColAdd, 1),"update_time": time.Now(),})if err != nil {return err}if num == 0 {return fmt.Errorf("Failed to increase repository pull count with name: %s", name)}return nil }

除此之外,在路由文件中還可以看到config.WithChartMuseum()配置,如果在全局配置中配置了with_chartmuseum=true,則就會(huì)開啟 Helm Chart 倉庫所需要的 API,相關(guān)的請(qǐng)求處理方法位于文件src/core/api/chart_repository.go文件中。

除了上面的一些主要功能之外,Harbor 還有很多高級(jí)可能,感興趣的同學(xué)可以下載 Harbor 的源碼自行研究,當(dāng)我們對(duì)源碼比較熟悉之后,對(duì)于我們搭建 Harbor 顯然是非常有幫助的,下節(jié)課給大家介紹怎樣在 Kubernetes 集群中來搭建 Harbor。

推薦

最后打個(gè)廣告,給大家推薦一個(gè)本人精心打造的一個(gè)精品課程,現(xiàn)在限時(shí)優(yōu)惠中:從 Docker 到 Kubernetes 進(jìn)階

微信搜索k8s技術(shù)圈關(guān)注我們的微信公眾帳號(hào),在微信公眾帳號(hào)中回復(fù) 加群 即可加入到我們的 kubernetes 討論群里面共同學(xué)習(xí)。

總結(jié)

以上是生活随笔為你收集整理的harbor登录验证_Harbor 源码浅析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

国内成人精品视频 | 欧美一级片免费播放 | 丁香在线观看完整电影视频 | 五月婷婷视频在线 | 欧美日韩不卡一区二区 | 成人精品99 | 99精品视频精品精品视频 | 麻豆视频免费在线观看 | 成人免费视频免费观看 | 国产日韩视频在线播放 | 在线视频黄 | 欧美日韩一区二区三区免费视频 | 中文字幕在线观看视频网站 | 亚洲精品456在线播放乱码 | 久久欧洲视频 | 久久6精品 | 日本少妇高清做爰视频 | 中文字幕在线观看第二页 | 又色又爽又激情的59视频 | 久久美女电影 | 日日摸日日 | 精品久久久亚洲 | 久久免费播放 | 99精品国产亚洲 | 久草爱 | 国产五月婷婷 | 日本成人a | 精品国产一区二区三区日日嗨 | 精品亚洲成人 | 四虎欧美| 日韩精品中文字幕一区二区 | 日本视频网 | 成人97人人超碰人人99 | 精品视频久久 | 成人av资源在线 | 四虎免费av | 丁香导航| 久草爱 | 亚洲欧洲视频 | 狠狠色丁香婷婷综合 | 亚洲国产精品资源 | 国产在线一区观看 | 在线免费试看 | 日韩欧美精品一区二区 | 欧美大片在线观看一区 | 夜夜操天天| 久久这里只有精品23 | av电影一区二区 | 黄色成人免费电影 | 黄色视屏在线免费观看 | 在线观看爱爱视频 | 在线探花 | 国产精品99免视看9 国产精品毛片一区视频 | 亚洲精品在线观看av | 国产亚洲精品久久久久久大师 | 精品国产一区二区三区不卡 | 欧洲亚洲女同hd | 国产精选在线观看 | 91一区二区三区久久久久国产乱 | 精品国内自产拍在线观看视频 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 亚洲夜夜网 | 在线看黄色的网站 | av片在线观看免费 | 91网站免费观看 | 丁香网五月天 | 国产 av 日韩 | 亚洲 欧美 91 | 99热超碰| 一区二区欧美激情 | 日韩视频免费在线观看 | 日韩av三区 | 国产高清综合 | 九月婷婷人人澡人人添人人爽 | 亚洲人成在线观看 | 久久成人黄色 | 久久人人爽人人爽人人 | 99色精品视频 | 欧美日韩免费在线视频 | 91精品一区在线观看 | 国产精品久久久999 国产91九色视频 | 美女视频是黄的免费观看 | 九色琪琪久久综合网天天 | 免费高清在线观看成人 | 国产做aⅴ在线视频播放 | 国产不卡高清 | 日韩精品专区在线影院重磅 | 久久精品视频2 | 亚洲精品综合欧美二区变态 | 亚洲资源在线观看 | 午夜国产福利在线 | 青青河边草观看完整版高清 | 91资源在线 | 中文字幕永久免费 | 免费观看成人网 | 九九电影在线 | 麻豆激情电影 | 日韩中文在线电影 | avcom在线 | 午夜视频在线网站 | 丁香五香天综合情 | www.香蕉 | 色爱区综合激月婷婷 | 国产黄色大片免费看 | 久久久久亚洲精品国产 | 日韩精品免费一线在线观看 | 精品免费视频. | 麻豆视频国产精品 | 在线有码中文字幕 | 国产精品网在线观看 | 麻豆国产精品va在线观看不卡 | avv天堂| 国产视频九色蝌蚪 | 婷婷5月激情5月 | 中文字幕精品视频 | 日韩av在线小说 | 国产999精品久久久 免费a网站 | 日韩久久激情 | 国产精品美 | 国产精品免费麻豆入口 | 欧美aa一级 | 国产在线国偷精品产拍 | 国产丝袜一区二区三区 | 少妇精品久久久一区二区免费 | 国产99久久精品一区二区永久免费 | 日日干天天爽 | 一级黄色片在线免费观看 | 人人搞人人干 | 亚洲精品乱码久久久久久 | 国产精品高清一区二区三区 | av在线com | 国产一级免费观看视频 | 成人福利av | 91精品国产自产在线观看永久 | 久久99精品久久久久久秒播蜜臀 | 日批视频 | 久草资源在线观看 | 国产精品福利在线播放 | 国产精品粉嫩 | 久久国产精品二国产精品中国洋人 | 成人日韩av| 99精品久久久久 | 伊人五月婷 | 91av视频在线免费观看 | 国产精品久久久久久久妇 | 国产中文字幕视频在线观看 | 国产成人亚洲在线观看 | 亚洲激情校园春色 | 国产日韩在线观看一区 | 亚洲综合色av | 亚洲国产精品视频在线观看 | 欧美先锋影音 | 免费福利在线播放 | 欧美极品久久 | 欧美性视频网站 | 中文字幕一区二区三区久久蜜桃 | 美女视频黄免费网站 | 亚洲aⅴ久久精品 | 国产精品剧情 | 探花视频在线观看免费 | 中文字幕字幕中文 | 日韩高清免费在线观看 | 国产麻豆视频 | 808电影免费观看三年 | 涩涩在线 | 亚洲精品视频在线免费 | 国产色中涩 | 免费观看午夜视频 | 亚洲人人网 | 久草在线手机视频 | 国产中文字幕在线看 | 色精品视频 | 中文字幕999| 日韩大片在线播放 | 成人免费视频网 | 色狠狠综合天天综合综合 | 婷婷激情在线 | 日韩高清片| 伊人狠狠干 | av电影一区二区 | 久久久久欠精品国产毛片国产毛生 | www黄色com| 国产精品网站一区二区三区 | 激情丁香综合五月 | 一级一片免费视频 | 国内99视频| 日韩一二三 | 日本激情中文字幕 | 狠狠色噜噜狠狠狠合久 | 人人澡澡人人 | 久久夜色精品国产欧美乱 | 韩国三级av在线 | 亚洲日本欧美 | 天堂在线免费视频 | 日本韩国欧美在线观看 | 成人黄色国产 | 日韩精品中文字幕在线播放 | 国产欧美精品一区二区三区四区 | 91精品久久久久久粉嫩 | www.午夜色.com | 国产精品久久久久久久久久久久午夜 | 久久少妇免费视频 | 激情久久婷婷 | 久久av网 | 免费看的黄色 | 激情开心站 | 欧美综合国产 | 欧美大片mv免费 | 久久久久国产成人精品亚洲午夜 | 天天射天天爱天天干 | 久草视频免费在线观看 | 国产专区一 | 欧美a级一区二区 | 91九色视频导航 | 在线国产一区二区三区 | 国产亚洲久一区二区 | 有码中文在线 | 九九免费在线观看视频 | 国产老太婆免费交性大片 | 色爱区综合激月婷婷 | av官网| 久久综合九色综合97_ 久久久 | 国产精品久久久区三区天天噜 | 午夜精品久久久久久久99水蜜桃 | 欧美日本啪啪无遮挡网站 | 亚洲成人精品国产 | 亚洲激情视频 | 午夜视频在线观看网站 | 久久国产精品一二三区 | 亚洲精品久久久蜜桃直播 | 久久久久久欧美二区电影网 | 97超碰总站| 成 人 黄 色 免费播放 | 日本成人中文字幕在线观看 | 一区二区欧美激情 | 色综合久久五月天 | 国产女人40精品一区毛片视频 | 色播五月激情综合网 | 亚洲成a人片77777潘金莲 | 麻豆免费观看视频 | 色黄久久久久久 | 久草在线免费资源 | 久久久久久美女 | 婷婷综合影院 | 欧洲亚洲精品 | 亚洲精品在线国产 | 日韩精品久久一区二区 | 国产精品成人久久 | 99久久久国产精品免费观看 | 亚洲在线黄色 | 国产精品资源在线 | 久久a v电影| 久久不射电影院 | 字幕网资源站中文字幕 | 91精品伦理| 久久精品这里热有精品 | 成人一级电影在线观看 | 欧美日比视频 | 91视频免费播放 | 国产精品18久久久久久首页狼 | 黄色小说免费观看 | 97爱| 亚洲国产成人久久综合 | 国产精品久久久久久久久久新婚 | 午夜精品久久久久久久久久久久久久 | 国产原创在线视频 | 91高清完整版在线观看 | 91精品视屏 | 91在线观看黄| 久久国产品 | 超碰免费久久 | 国产在线观看中文字幕 | 中文字幕免费在线看 | 黄色网www| 97超碰人人 | 开心综合网 | www.五月天| 久久久国产日韩 | 911久久| 在线观看黄色小视频 | 探花视频在线观看免费版 | 亚洲精品欧美视频 | 日韩手机视频 | 精品免费在线视频 | 亚洲精品在线观看网站 | 黄色精品一区 | 久久国精品 | 五月激情姐姐 | 韩国av一区二区三区 | 在线中文字幕观看 | 天天激情综合 | 国产精品一区二区三区视频免费 | 中文字幕91 | 久久久亚洲电影 | 天天天天爱天天躁 | av看片网址 | 中文字幕在线视频一区二区三区 | 国产又粗又猛又色又黄视频 | 午夜国产一区二区三区四区 | 丁香五月亚洲综合在线 | 欧美精品一区二区蜜臀亚洲 | 久久久精品国产免费观看一区二区 | 久久精品中文字幕一区二区三区 | 国产精品久久久久久久午夜片 | 国内外激情视频 | 天天操天天干天天综合网 | 久久久视频在线 | 丁香5月婷婷久久 | 久久精品国产精品亚洲精品 | 国产91亚洲精品 | 国产理论一区二区三区 | 久久精品三级 | 国产一区二区在线播放 | 久久免费视频2 | 九九久久国产 | 欧美与欧洲交xxxx免费观看 | 欧美激情视频一二三区 | 天天摸天天弄 | 欧美精品乱码99久久影院 | 亚洲精品中文字幕在线观看 | 精品国产1区2区3区 国产欧美精品在线观看 | 91中文字幕网 | 日韩欧美在线综合网 | 久久久久国产精品免费免费搜索 | 婷五月激情 | 国产成人免费 | 91成人亚洲 | 99久久99视频只有精品 | 波多野结衣动态图 | 五月婷婷丁香激情 | 国产精品一区二区美女视频免费看 | 又色又爽又黄 | 人人爽人人爽人人片 | 国产片免费在线观看视频 | 午夜视频在线观看一区二区 | a午夜电影 | 久草www| 国产一级黄色免费看 | 国产97在线观看 | 久久久精品网站 | 在线观看免费中文字幕 | 91精品啪在线观看国产81旧版 | 中文字幕一区av | 国产亚洲综合在线 | 在线免费观看麻豆 | 国产精品一区二区久久精品爱微奶 | 婷婷丁香六月天 | 四虎影视精品永久在线观看 | 人人插人人搞 | 亚洲视频在线观看 | 日韩城人在线 | 日批视频在线 | 午夜精品福利影院 | 黄色三级网站在线观看 | 一区二区中文字幕在线观看 | a电影免费看 | 精品国产91亚洲一区二区三区www | 中文字幕观看视频 | 波多野结衣在线观看一区二区三区 | 99久免费精品视频在线观看 | 精品国产一区二区三区不卡 | 日韩中文字幕免费视频 | 91成人观看 | 天天草天天插 | 欧美精品中文在线免费观看 | 国产日韩中文字幕在线 | 99视频在线观看视频 | 午夜美女福利 | 日日摸日日添夜夜爽97 | 欧美伦理电影一区二区 | 久久久久久久久久亚洲精品 | 青青久草在线视频 | 日韩久久精品一区二区 | 日韩在线免费视频观看 | 欧洲一区二区三区精品 | 成人黄色在线视频 | 97超碰人人澡| 亚洲精品美女在线观看播放 | 久久久久久久99 | 天天爽天天射 | 三级动态视频在线观看 | 6080yy午夜一二三区久久 | 欧美色婷 | 97成人在线观看 | 国产精品美女久久久久久网站 | 特级西西人体444是什么意思 | 欧美男同视频网站 | 人人澡超碰碰97碰碰碰软件 | 久草a视频 | 亚洲精品乱码久久久久久9色 | 久久午夜电影 | 欧美怡红院视频 | 久久久久久久久久久久久久电影 | 国产成人精品一区二区 | 中文不卡视频在线 | 免费精品在线视频 | 成人九九视频 | 亚洲一区二区三区在线看 | 久久国产精品久久w女人spa | 久久久久久久久毛片精品 | 免费av成人在线 | 亚洲无人区小视频 | 久热国产视频 | 激情婷婷网 | 日本久久久久久久久久久 | 国产成人精品一区二三区 | av电影在线观看 | 国内精品久久久精品电影院 | 精品久久久久久久久久岛国gif | 久草在线免费新视频 | 久久久久久久久久久福利 | 亚洲国产欧美在线看片xxoo | 亚洲高清av | 三级在线视频观看 | 在线观看日韩专区 | 美女视频免费一区二区 | www.91av在线| 福利视频一区二区 | 久久国产一二区 | 亚洲精品福利在线观看 | 国产免费不卡 | 天天色天 | 91麻豆精品国产91久久久久久久久 | 婷婷六月综合亚洲 | 91麻豆精品久久久久久 | 91九色精品女同系列 | 久久综合九色综合久久久精品综合 | 亚洲精品国产精品国自产 | 综合激情婷婷 | 成 人 黄 色 视频 免费观看 | 成年人黄色免费看 | 91超碰在线播放 | 日韩欧美在线国产 | 美女久久久久 | 正在播放日韩 | 日本中文一级片 | 国产精品成人免费精品自在线观看 | 黄色av网站在线免费观看 | 国产99久久精品一区二区300 | 国产一级电影免费观看 | 九九九电影免费看 | 在线免费黄 | 免费www视频 | 最近字幕在线观看第一季 | 国产啊v在线观看 | 视频一区二区精品 | 一区二区三区国产欧美 | avwww在线| 久久久久久久久毛片精品 | 在线视频久久 | 日韩欧美精品在线观看视频 | www.成人精品 | 99久久婷婷国产一区二区三区 | 日本爱爱免费视频 | 青草视频免费观看 | 日韩精品免费一线在线观看 | 精品a视频 | 久久久久久久久久久久久国产精品 | 97天堂网| 精品一二三区视频 | av电影久久| 国产麻豆传媒 | 在线免费观看亚洲视频 | 韩国av一区 | 黄色片网站av | 久久综合九色九九 | 免费在线国产视频 | 国产视频精品免费播放 | 日韩理论在线视频 | av三级av| 国产亚洲精品久久久久久久久久久久 | 91天天操 | 91手机电视 | 免费黄色a级毛片 | 中文字幕精品在线 | 97综合在线 | 国产中文在线视频 | 欧美精品久久久久久久亚洲调教 | 久久免费久久 | 91视频在线观看下载 | 在线之家免费在线观看电影 | 在线黄色观看 | 久久成人免费 | 免费三级av | 91看片一区二区三区 | 欧美日韩一区二区久久 | 不卡av电影在线 | 中文字幕成人 | 国产日产精品久久久久快鸭 | 一区二区三区中文字幕在线 | 蜜臀久久99精品久久久久久网站 | 色插综合 | 日韩在线观看视频在线 | 亚洲一片黄 | 中文字幕一区二区在线播放 | 国产国语在线 | 91看片麻豆| 久久手机免费观看 | 天天鲁一鲁摸一摸爽一爽 | 久久久久久毛片精品免费不卡 | 欧美日韩国产综合一区二区 | 久久1电影院 | www..com黄色片| 成人久久视频 | 中文字幕国产一区二区 | 午夜免费福利片 | 成人国产精品电影 | 天天色天天操天天爽 | 久久精品国亚洲 | 色婷婷99 | 亚洲黄网站 | 久久综合中文字幕 | 亚洲伊人网在线观看 | 手机在线看片日韩 | 黄色一区三区 | 日韩精品资源 | 伊人精品在线 | 亚洲精品www. | 国产色视频一区 | 黄色av网站在线观看免费 | 在线观看成人网 | 色婷婷视频在线 | 中国一级片在线 | 免费日韩 精品中文字幕视频在线 | 午夜视频色 | 99人久久精品视频最新地址 | 精品国产伦一区二区三区观看方式 | 欧美激情第八页 | 久久tv视频 | 天天爽天天爽夜夜爽 | 人人爱人人射 | 成人国产精品一区二区 | 久久一区91 | av在线免费不卡 | 国产精品白丝av | 精品一二三四视频 | 久久一区91 | av天天草| 亚洲电影影音先锋 | 久久精品国产精品亚洲 | 婷婷日| 欧美一区二区免费在线观看 | 日本精品午夜 | 一级黄色免费网站 | 91九色老| 久产久精国产品 | 免费裸体视频网 | 国产视频久久 | 国产精品网站一区二区三区 | 国产精品6 | 国产美女精品人人做人人爽 | 欧美一区二区在线刺激视频 | 免费 在线 中文 日本 | 天天干天天看 | 最新中文字幕在线观看视频 | 国产高清视频免费在线观看 | av电影亚洲| 亚洲精品视频免费在线 | 国产一区二区三区视频在线 | 欧美性色19p | 911亚洲精品第一 | 久久tv | 日韩精品在线看 | 亚洲爱爱视频 | 国产精品久久久亚洲 | 久久天天操| 三级动态视频在线观看 | 国产精品美女久久久久aⅴ 干干夜夜 | 在线观看日本韩国电影 | 久久久久国产视频 | 日本久久成人中文字幕电影 | 国产精品嫩草在线 | 国产男女无遮挡猛进猛出在线观看 | 欧美久草视频 | 日韩激情视频在线 | 色婷婷久久 | 国产破处视频在线播放 | 91麻豆网站| 91精品老司机久久一区啪 | 亚洲综合色丁香婷婷六月图片 | 中文字幕在线观看91 | 久久精品99国产精品日本 | 日韩欧美精品一区二区 | av夜夜操 | 国产精品女同一区二区三区久久夜 | 日韩大片在线观看 | 国产精品麻豆果冻传媒在线播放 | 成人一级片在线观看 | 久久一区二区三区日韩 | 日韩欧美一区视频 | 中文亚洲欧美日韩 | 欧美黄色特级片 | 狠狠色狠狠色合久久伊人 | 综合久久久久久久久 | 五月婷婷综合在线视频 | 亚洲免费小视频 | 波多野结衣一区三区 | 久久a免费视频 | 91久久久久久久一区二区 | 国产麻豆视频免费观看 | 成人av在线一区二区 | 黄色av大片 | 久久99热这里只有精品国产 | 国产成人精品一区二三区 | 国产视频1区2区3区 久久夜视频 | 国产91在线 | 美洲 | 欧美成人h版在线观看 | 中文av资源站| 91麻豆精品国产 | 五月天电影免费在线观看一区 | 2020天天干夜夜爽 | 亚洲女同videos| 色 免费观看 | 96国产在线 | 久久免费视频在线 | 国产精品综合av一区二区国产馆 | 99九九99九九九视频精品 | 久久国产区 | 久久久久久免费网 | 色com网 | 高清av不卡| 一区二区三区电影在线播 | 高清有码中文字幕 | 伊人天天色 | 丰满少妇在线观看资源站 | 开心激情综合网 | 亚洲影院一区 | www.av免费 | 亚洲伦理一区 | 欧美日韩不卡在线 | 欧美孕交vivoestv另类 | 91黄色影视 | 久久精品1区2区 | 99久久99视频 | 麻豆精品视频在线观看免费 | 国产精品毛片一区二区 | 久久国产成人午夜av影院潦草 | 伊人国产在线观看 | 人人爱人人爽 | 国产欧美日韩视频 | 精品一二 | 91视频在线网址 | 色av男人的天堂免费在线 | 91av久久| 91亚洲精| 日韩大片在线免费观看 | 精壮的侍卫呻吟h | 97成人在线视频 | 国产精品久久99精品毛片三a | 久久久久久久久久毛片 | av在线短片| 91av在线播放 | 摸bbb搡bbb搡bbbb | 欧美xxxxx在线视频 | 亚洲更新最快 | 亚洲亚洲精品在线观看 | 蜜臀av夜夜澡人人爽人人 | 黄色福利网站 | 精品久久1 | 精品国产精品久久 | 久青草视频在线观看 | 日本婷婷色 | 国产精品久久久久四虎 | 毛片网免费 | 在线观看av大片 | 久草视频在线看 | 国产剧情一区 | 色综合天天狠天天透天天伊人 | 一区二区三区在线不卡 | 亚洲一区二区三区四区精品 | 69精品| 久久婷五月| 色偷偷88欧美精品久久久 | 高清一区二区三区av | 三级黄色网络 | 午夜国产福利在线观看 | 国产精品私人影院 | 黄色软件网站在线观看 | 欧美激情视频一区二区三区 | 国产日韩中文字幕 | 91精品国产欧美一区二区 | 久久精品波多野结衣 | 亚洲 欧洲 国产 精品 | 91精品国产网站 | 夜色资源站国产www在线视频 | 中文字幕美女免费在线 | 五月婷婷激情综合 | 狠狠干狠狠色 | 久久久久看片 | 91在线观看视频网站 | 97精品国产91久久久久久 | 91网在线看 | 伊人五月天 | 一区二区三区四区免费视频 | 97国产在线视频 | 最近中文字幕高清字幕免费mv | 精品国产自在精品国产精野外直播 | 亚洲精品国产精品国 | 97视频在线免费 | 97成人免费视频 | 成年人电影免费在线观看 | 亚洲91精品 | 久久久久久久久久久黄色 | 午夜精品一区二区三区在线 | 香蕉视频亚洲 | 麻豆视频免费在线播放 | 国产午夜三级一区二区三桃花影视 | 黄色三级免费观看 | 国产一区欧美在线 | 91激情小视频| 东方av在| 日韩视频免费观看高清完整版在线 | 久久综合色婷婷 | 精品国产美女 | 日本精品va在线观看 | 天天操天天操天天干 | 国产黄色精品在线 | 一区二区精品视频 | 91成人短视频在线观看 | 国产伦理一区 | 久久夜色电影 | 精品高清美女精品国产区 | 久久视频一区二区 | 中文字幕中文字幕在线中文字幕三区 | 久久视频在线免费观看 | 蜜桃视频在线视频 | 日韩高清一区在线 | 欧美日韩国产一二三区 | 99这里只有久久精品视频 | 成人久久久久久久久久 | 日一日操一操 | 久久成人欧美 | 视色网站 | 国产最新在线观看 | 久久夜视频 | 色婷婷在线观看视频 | 99久热在线精品视频成人一区 | 天天色棕合合合合合合 | 五月天亚洲综合小说网 | 日韩中文字幕在线不卡 | 69av在线视频 | 久久99精品国产麻豆宅宅 | 97色噜噜 | 操高跟美女 | 欧美十八 | 亚洲 成人 欧美 | www色片 | 国产高清在线一区 | 少妇高潮流白浆在线观看 | 色视频在线观看免费 | 三级在线视频观看 | 视频 天天草 | 国产手机视频在线播放 | 天天色成人网 | 午夜在线看 | 999国产精品视频 | 国产露脸91国语对白 | 色偷偷人人澡久久超碰69 | 91新人在线观看 | 国产97超碰 | 麻豆视频免费看 | 日韩精品中文字幕久久臀 | 精品毛片一区二区免费看 | 国产精品久久中文字幕 | 国产精品一区一区三区 | 91麻豆精品国产91久久久更新时间 | 色片网站在线观看 | 午夜精品一二三区 | 日日夜av| 91免费网 | 亚洲日本va午夜在线影院 | 五月婷在线播放 | 成人av资源在线 | 丁香婷婷激情国产高清秒播 | 亚洲精品97 | 亚洲天堂网在线观看视频 | 91成人精品国产刺激国语对白 | www..com毛片| 成人免费毛片aaaaaa片 | 久久国产精品99久久久久久丝袜 | 婷婷婷国产在线视频 | 韩日三级av| 欧美91精品久久久久国产性生爱 | 中文字幕亚洲欧美 | 精品国产一区二区三区久久 | 999视频在线观看 | 久久人人97超碰精品888 | 精品伊人久久久 | 午夜私人影院久久久久 | 91亚色视频| 久久永久免费视频 | 五月天丁香视频 | 国产精品久久久久久一区二区 | av福利在线 | 日韩欧美在线观看一区二区三区 | 欧美精品国产综合久久 | 中文字幕色婷婷在线视频 | 久久久精品免费观看 | 麻豆视频在线免费观看 | 久99视频 | 麻豆视频免费在线观看 | 亚洲另类视频在线 | av福利在线看 | 香蕉影院在线播放 | 日韩成人在线免费观看 | 国产精品久久久久久麻豆一区 | 97碰碰精品嫩模在线播放 | 日韩福利在线观看 | 欧美黑人xxxx猛性大交 | av免费在线播放 | 天天干天天操天天射 | 亚洲黄色小说网 | 911久久| 国产精品一区二区三区免费视频 | 精品国自产在线观看 | 人人爽人人做 | 成人国产精品免费观看 | 亚洲国产成人av网 | 精品日本视频 | 免费在线一区二区三区 | 一本大道久久精品懂色aⅴ 五月婷社区 | 中文字幕高清在线 | 欧美婷婷综合 | 久久99热这里只有精品国产 | 激情视频免费在线 | 91人人人| 六月色丁 | 综合激情av | 日韩中文字幕a | 91av精品| www.黄色网.com | 中文字幕观看在线 | 精品免费视频. | 永久中文字幕 | 国产涩涩在线观看 | 亚洲在线国产 | 在线观看视频在线 | 国产99久久久欧美黑人 | 国产免费激情久久 | 天堂av在线网 | 国产精品久久久久一区二区国产 | 国产免费黄色 | 超碰97公开 | 九九综合久久 | 免费国产黄线在线观看视频 | 最近免费中文视频 | 97超碰成人在线 | 国产精品毛片一区 | 久草在线免费资源 | 精品一区二区视频 | www.日日日.com| 国产99久久九九精品免费 | 黄色一级免费电影 | 亚洲欧美成人网 | 国产精品免费观看在线 | 国产一性一爱一乱一交 | 九九视频免费观看视频精品 | 久久免费影院 | 在线免费色 | 久久精品视频在线免费观看 | 国产日产精品一区二区三区四区的观看方式 | 一级片免费观看 | av东方在线 | 中文字幕在线免费观看视频 | 久久久色 | 在线观看国产一区二区 | 天天干天天干天天干天天干天天干天天干 | 免费在线a| 国产一级片直播 | 久久久国产影院 | 成人免费观看完整版电影 | 国产视频九色蝌蚪 | 91九色视频导航 | 国产精品一区二区三区四区在线观看 | 欧美色图88 | 久久综合久久综合久久 | 97偷拍视频 | 国产午夜精品视频 | 91麻豆.com| 国产精品久久久久久久久久东京 | 日韩网站免费观看 | 天天操导航 | 国产精品久久久久影视 | 亚洲春色成人 | 国产精品女同一区二区三区久久夜 | 免费观看成人 | 亚洲免费专区 | 免费看黄色毛片 | 伊人五月综合 | av大片网站| 婷婷在线不卡 | 亚洲久草在线 | 在线视频观看成人 | 精品久久久久亚洲 | 国产麻豆精品久久 | 国产啊v在线观看 | 久久天堂影院 | 日日夜夜草 | 欧美成人tv| 蜜臀av性久久久久蜜臀aⅴ流畅 | 激情五月婷婷综合 | 黄色av免费 | 国产精品网址在线观看 | 亚洲精品电影在线 | 国产精品青草综合久久久久99 | 在线www色| 亚洲女人av| 中文字幕亚洲综合久久五月天色无吗'' | 久草在线视频免费资源观看 | 国产一区在线免费观看 | 国产精品欧美久久久久三级 | 色婷婷骚婷婷 | 午夜三级大片 | 婷婷中文字幕在线观看 | 成人av播放| 在线视频第一页 | 国产精品wwwwww | 日韩欧美综合精品 | 国产精品激情 | 1024久久| 日韩免费观看一区二区三区 | 丁香花中文在线免费观看 | 久久色网站 | 日韩黄色一级电影 | 中文字幕色在线 | 婷婷深爱网 | 韩日av在线| 欧美日韩视频在线 | 久久久久久不卡 | 黄色动态图xx | 精品在线亚洲视频 | 丁香九月激情综合 | 免费观看成人网 | 丁香婷婷网 | 国产精品女主播一区二区三区 | 麻豆91精品 | 国产视频日韩视频欧美视频 | 午夜精品剧场 | 操操操影院 | 中文字幕在线专区 | 婷婷六月在线 | 区一区二在线 | av电影在线免费 | 日韩专区一区二区 | 亚洲第一色 | 91av在线免费观看 | 国产精品第10页 | 午夜色影院 | 日日婷婷夜日日天干 | 91传媒免费观看 | 色噜噜在线观看 | 天天色天天操综合网 | 国产欧美久久久精品影院 | 久久www免费人成看片高清 | 欧美成人亚洲成人 | 国产1区2区3区精品美女 | 国产韩国精品一区二区三区 | 韩国av免费观看 | 免费人成网ww44kk44 | 国产精品久久久久久吹潮天美传媒 | 久久艹欧美 | 2023亚洲精品国偷拍自产在线 | 91麻豆精品国产 | 欧美在线一级片 | 欧美日韩三级 | 在线观看视频免费大全 | 国产一级视屏 | 午夜精品久久久久久久99 | 久久久久国产精品www | 国产91精品一区二区麻豆亚洲 | 国产又粗又猛又黄又爽视频 | 国产精品99久久久精品免费观看 | 国产精品久久久区三区天天噜 | 九色91在线视频 | 精品电影一区 | 国产精品免费看久久久8精臀av | 国产小视频网站 | 日韩黄色大片在线观看 | 中文字幕麻豆 | 911精品美国片911久久久 | 探花在线观看 | 亚洲精品免费在线 | 国产一二三精品 | 国产二级视频 | 97人人模人人爽人人喊网 | 日韩高清在线一区二区三区 | 国产999视频在线观看 | 国产黄色特级片 | 青青河边草观看完整版高清 | 在线免费中文字幕 | 亚洲国产影院av久久久久 | 日韩国产欧美在线视频 | 精品毛片一区二区免费看 | 日韩精品资源 | 探花国产在线 | 96国产在线| v片在线播放 | 亚洲精品久久久蜜臀下载官网 |