通过OAuth方式与docker hub v2 API交互

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 介绍docker hub的 OAuth调用过程

缘由

Docker hub提供V2版本接口后,使用了新的认证授权方式,需要通过OAuth的认证授权方式来调用其API。本文主要是演示获取某个镜像的tag的列表过程,其它接口调用方式类似
本例子使用了httpie工具,如果在mac下可以用过brew方式安装

brew install httpie

交互过程

先直接调用需要的资源

这里以查询nginx的tag列表为例

http https://registry.hub.docker.com/v2/library/nginx/tags/list

这个时候,因为没有获取到授权,所以服务会返回需要授权的相关信息

HTTP/1.1 401 Unauthorized
Content-Length: 156
Content-Type: application/json; charset=utf-8
Date: Wed, 05 Sep 2018 03:05:35 GMT
Docker-Distribution-Api-Version: registry/2.0
Strict-Transport-Security: max-age=31536000
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/nginx:pull"

{
    "errors": [
        {
            "code": "UNAUTHORIZED",
            "detail": [
                {
                    "Action": "pull",
                    "Class": "",
                    "Name": "library/nginx",
                    "Type": "repository"
                }
            ],
            "message": "authentication required"
        }
    ]
}

注意"Www-Authenticate"这个http头,这个是我们需要进行认证授权的信息

  • Bearer realm: 是进行授权服务器的地址
  • service: 是试用的服务信息
  • scope: 是授权的范围

有了这些对应的信息,我们就可以调用授权服务来进行授权了

使用用户名密码授权

http -a <用户名>:<密码> https://auth.docker.io/token  service==registry.docker.io scope==repository:library/nginx:pull

如果认证通过,则会返回对应的授权信息

HTTP/1.1 200 OK
Content-Type: application/json
Date: Wed, 05 Sep 2018 03:08:20 GMT
Strict-Transport-Security: max-age=31536000
Transfer-Encoding: chunked

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsIng1YyI6WyJNSUlDK2pDQ0FwK2dBd0lCQWdJQkFEQUtCZ2dxaGtqT1BRUURBakJHTVVRd1FnWURWUVFERXpzeVYwNVpPbFZMUzFJNlJFMUVVanBTU1U5Rk9reEhOa0U2UTFWWVZEcE5SbFZNT2tZelNFVTZOVkF5VlRwTFNqTkdPa05CTmxrNlNrbEVVVEFlRncweE9EQXlNVFF5TXpBMk5EZGFGdzB4T1RBeU1UUXlNekEyTkRkYU1FWXhSREJDQmdOVkJBTVRPMVpCUTFZNk5VNWFNenBNTkZSWk9sQlFTbGc2VWsxQlZEcEdWalpQT2xZMU1sTTZRa2szV2pwU1REVk9PbGhXVDBJNlFsTmFSanBHVTFRMk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMGtyTmgyZWxESnVvYjVERWd5Wi9oZ3l1ZlpxNHo0OXdvNStGRnFRK3VPTGNCMDRyc3N4cnVNdm1aSzJZQ0RSRVRERU9xNW5keEVMMHNaTE51UXRMSlNRdFY1YUhlY2dQVFRkeVJHUTl2aURPWGlqNFBocE40R0N0eFV6YTNKWlNDZC9qbm1YbmtUeDViOElUWXBCZzg2TGNUdmMyRFVUV2tHNy91UThrVjVPNFFxNlZKY05TUWRId1B2Mmp4YWRZa3hBMnhaaWNvRFNFQlpjWGRneUFCRWI2YkRnUzV3QjdtYjRRVXBuM3FXRnRqdCttKzBsdDZOR3hvenNOSFJHd3EwakpqNWtZbWFnWHpEQm5NQ3l5eDFBWFpkMHBNaUlPSjhsaDhRQ09GMStsMkVuV1U1K0thaTZKYVNEOFZJc2VrRzB3YXd4T1dER3U0YzYreE1XYUx3SURBUUFCbzRHeU1JR3ZNQTRHQTFVZER3RUIvd1FFQXdJSGdEQVBCZ05WSFNVRUNEQUdCZ1JWSFNVQU1FUUdBMVVkRGdROUJEdFdRVU5XT2pWT1dqTTZURFJVV1RwUVVFcFlPbEpOUVZRNlJsWTJUenBXTlRKVE9rSkpOMW82VWt3MVRqcFlWazlDT2tKVFdrWTZSbE5VTmpCR0JnTlZIU01FUHpBOWdEc3lWMDVaT2xWTFMxSTZSRTFFVWpwU1NVOUZPa3hITmtFNlExVllWRHBOUmxWTU9rWXpTRVU2TlZBeVZUcExTak5HT2tOQk5sazZTa2xFVVRBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQWdZTWF3Si9uMXM0dDlva0VhRjh2aGVkeURzbERObWNyTHNRNldmWTFmRTRDSVFEbzNWazJXcndiSjNmU1dwZEVjT3hNazZ1ZEFwK2c1Nkd6TjlRSGFNeVZ1QT09Il19.eyJhY2Nlc3MiOlt7InR5cGUiOiJyZXBvc2l0b3J5IiwibmFtZSI6ImxpYnJhcnkvbmdpbngiLCJhY3Rpb25zIjpbInB1bGwiXX1dLCJhdWQiOiJyZWdpc3RyeS5kb2NrZXIuaW8iLCJleHAiOjE1MzYxMTcyMDAsImlhdCI6MTUzNjExNjkwMCwiaXNzIjoiYXV0aC5kb2NrZXIuaW8iLCJqdGkiOiJiek81UDd4VWZPdG1raXFfcUtvZCIsIm5iZiI6MTUzNjExNjYwMCwic3ViIjoiZDk0MTY0MzgtNzRjMC0xMWU0LWJlYTQtMDI0MmFjMTEwMDFiIn0.TSVfcHfpAe-HuzmJ1V-AixLSotEdtQU_zYgXfkomWVbPz8wZx_DtTZRUmMaW7X0J37MpQbrABCeRD-ZlY7TCa7IliGXZISWgB7mn89mENHWnEB-1FyyUqH5XS4kTtG7XEY-bx3nlxQybtqrYFhroVUsxuXzsrTax0OmdZH07Gyi3K3Diszipu4QejSpdN-pVjvS3jUCFyI-dW3IALKEompe4zAuZ0Aux-yuEz4TxJDOGFVYry4F0OgNiFtlLGsO6vPbFloMRPaU6e3YCTgVkRjQbugOjamsB_0URcwJpuZO4qDisV2_faCY72TG_P240mv0Ui4ywvHMcn5YWVIAABQ",
    "expires_in": 300,
    "issued_at": "2018-09-05T03:08:20.971232202Z",
    "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsIng1YyI6WyJNSUlDK2pDQ0FwK2dBd0lCQWdJQkFEQUtCZ2dxaGtqT1BRUURBakJHTVVRd1FnWURWUVFERXpzeVYwNVpPbFZMUzFJNlJFMUVVanBTU1U5Rk9reEhOa0U2UTFWWVZEcE5SbFZNT2tZelNFVTZOVkF5VlRwTFNqTkdPa05CTmxrNlNrbEVVVEFlRncweE9EQXlNVFF5TXpBMk5EZGFGdzB4T1RBeU1UUXlNekEyTkRkYU1FWXhSREJDQmdOVkJBTVRPMVpCUTFZNk5VNWFNenBNTkZSWk9sQlFTbGc2VWsxQlZEcEdWalpQT2xZMU1sTTZRa2szV2pwU1REVk9PbGhXVDBJNlFsTmFSanBHVTFRMk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMGtyTmgyZWxESnVvYjVERWd5Wi9oZ3l1ZlpxNHo0OXdvNStGRnFRK3VPTGNCMDRyc3N4cnVNdm1aSzJZQ0RSRVRERU9xNW5keEVMMHNaTE51UXRMSlNRdFY1YUhlY2dQVFRkeVJHUTl2aURPWGlqNFBocE40R0N0eFV6YTNKWlNDZC9qbm1YbmtUeDViOElUWXBCZzg2TGNUdmMyRFVUV2tHNy91UThrVjVPNFFxNlZKY05TUWRId1B2Mmp4YWRZa3hBMnhaaWNvRFNFQlpjWGRneUFCRWI2YkRnUzV3QjdtYjRRVXBuM3FXRnRqdCttKzBsdDZOR3hvenNOSFJHd3EwakpqNWtZbWFnWHpEQm5NQ3l5eDFBWFpkMHBNaUlPSjhsaDhRQ09GMStsMkVuV1U1K0thaTZKYVNEOFZJc2VrRzB3YXd4T1dER3U0YzYreE1XYUx3SURBUUFCbzRHeU1JR3ZNQTRHQTFVZER3RUIvd1FFQXdJSGdEQVBCZ05WSFNVRUNEQUdCZ1JWSFNVQU1FUUdBMVVkRGdROUJEdFdRVU5XT2pWT1dqTTZURFJVV1RwUVVFcFlPbEpOUVZRNlJsWTJUenBXTlRKVE9rSkpOMW82VWt3MVRqcFlWazlDT2tKVFdrWTZSbE5VTmpCR0JnTlZIU01FUHpBOWdEc3lWMDVaT2xWTFMxSTZSRTFFVWpwU1NVOUZPa3hITmtFNlExVllWRHBOUmxWTU9rWXpTRVU2TlZBeVZUcExTak5HT2tOQk5sazZTa2xFVVRBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQWdZTWF3Si9uMXM0dDlva0VhRjh2aGVkeURzbERObWNyTHNRNldmWTFmRTRDSVFEbzNWazJXcndiSjNmU1dwZEVjT3hNazZ1ZEFwK2c1Nkd6TjlRSGFNeVZ1QT09Il19.eyJhY2Nlc3MiOlt7InR5cGUiOiJyZXBvc2l0b3J5IiwibmFtZSI6ImxpYnJhcnkvbmdpbngiLCJhY3Rpb25zIjpbInB1bGwiXX1dLCJhdWQiOiJyZWdpc3RyeS5kb2NrZXIuaW8iLCJleHAiOjE1MzYxMTcyMDAsImlhdCI6MTUzNjExNjkwMCwiaXNzIjoiYXV0aC5kb2NrZXIuaW8iLCJqdGkiOiJiek81UDd4VWZPdG1raXFfcUtvZCIsIm5iZiI6MTUzNjExNjYwMCwic3ViIjoiZDk0MTY0MzgtNzRjMC0xMWU0LWJlYTQtMDI0MmFjMTEwMDFiIn0.TSVfcHfpAe-HuzmJ1V-AixLSotEdtQU_zYgXfkomWVbPz8wZx_DtTZRUmMaW7X0J37MpQbrABCeRD-ZlY7TCa7IliGXZISWgB7mn89mENHWnEB-1FyyUqH5XS4kTtG7XEY-bx3nlxQybtqrYFhroVUsxuXzsrTax0OmdZH07Gyi3K3Diszipu4QejSpdN-pVjvS3jUCFyI-dW3IALKEompe4zAuZ0Aux-yuEz4TxJDOGFVYry4F0OgNiFtlLGsO6vPbFloMRPaU6e3YCTgVkRjQbugOjamsB_0URcwJpuZO4qDisV2_faCY72TG_P240mv0Ui4ywvHMcn5YWVIAABQ"
}

这里access_token就是用来访问资源的授权token。授权的token的类型是Bearer
备注:docker hub不太遵守OAuth2的标准,所以这里返回值,也和OAuth不太相同

通过授权key再度访问资源

http https://registry.hub.docker.com/v2/library/nginx/tags/list 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsIng1YyI6WyJNSUlDK2pDQ0FwK2dBd0lCQWdJQkFEQUtCZ2dxaGtqT1BRUURBakJHTVVRd1FnWURWUVFERXpzeVYwNVpPbFZMUzFJNlJFMUVVanBTU1U5Rk9reEhOa0U2UTFWWVZEcE5SbFZNT2tZelNFVTZOVkF5VlRwTFNqTkdPa05CTmxrNlNrbEVVVEFlRncweE9EQXlNVFF5TXpBMk5EZGFGdzB4T1RBeU1UUXlNekEyTkRkYU1FWXhSREJDQmdOVkJBTVRPMVpCUTFZNk5VNWFNenBNTkZSWk9sQlFTbGc2VWsxQlZEcEdWalpQT2xZMU1sTTZRa2szV2pwU1REVk9PbGhXVDBJNlFsTmFSanBHVTFRMk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMGtyTmgyZWxESnVvYjVERWd5Wi9oZ3l1ZlpxNHo0OXdvNStGRnFRK3VPTGNCMDRyc3N4cnVNdm1aSzJZQ0RSRVRERU9xNW5keEVMMHNaTE51UXRMSlNRdFY1YUhlY2dQVFRkeVJHUTl2aURPWGlqNFBocE40R0N0eFV6YTNKWlNDZC9qbm1YbmtUeDViOElUWXBCZzg2TGNUdmMyRFVUV2tHNy91UThrVjVPNFFxNlZKY05TUWRId1B2Mmp4YWRZa3hBMnhaaWNvRFNFQlpjWGRneUFCRWI2YkRnUzV3QjdtYjRRVXBuM3FXRnRqdCttKzBsdDZOR3hvenNOSFJHd3EwakpqNWtZbWFnWHpEQm5NQ3l5eDFBWFpkMHBNaUlPSjhsaDhRQ09GMStsMkVuV1U1K0thaTZKYVNEOFZJc2VrRzB3YXd4T1dER3U0YzYreE1XYUx3SURBUUFCbzRHeU1JR3ZNQTRHQTFVZER3RUIvd1FFQXdJSGdEQVBCZ05WSFNVRUNEQUdCZ1JWSFNVQU1FUUdBMVVkRGdROUJEdFdRVU5XT2pWT1dqTTZURFJVV1RwUVVFcFlPbEpOUVZRNlJsWTJUenBXTlRKVE9rSkpOMW82VWt3MVRqcFlWazlDT2tKVFdrWTZSbE5VTmpCR0JnTlZIU01FUHpBOWdEc3lWMDVaT2xWTFMxSTZSRTFFVWpwU1NVOUZPa3hITmtFNlExVllWRHBOUmxWTU9rWXpTRVU2TlZBeVZUcExTak5HT2tOQk5sazZTa2xFVVRBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQWdZTWF3Si9uMXM0dDlva0VhRjh2aGVkeURzbERObWNyTHNRNldmWTFmRTRDSVFEbzNWazJXcndiSjNmU1dwZEVjT3hNazZ1ZEFwK2c1Nkd6TjlRSGFNeVZ1QT09Il19.eyJhY2Nlc3MiOlt7InR5cGUiOiJyZXBvc2l0b3J5IiwibmFtZSI6ImxpYnJhcnkvbmdpbngiLCJhY3Rpb25zIjpbInB1bGwiXX1dLCJhdWQiOiJyZWdpc3RyeS5kb2NrZXIuaW8iLCJleHAiOjE1MzYxMTcyMDAsImlhdCI6MTUzNjExNjkwMCwiaXNzIjoiYXV0aC5kb2NrZXIuaW8iLCJqdGkiOiJiek81UDd4VWZPdG1raXFfcUtvZCIsIm5iZiI6MTUzNjExNjYwMCwic3ViIjoiZDk0MTY0MzgtNzRjMC0xMWU0LWJlYTQtMDI0MmFjMTEwMDFiIn0.TSVfcHfpAe-HuzmJ1V-AixLSotEdtQU_zYgXfkomWVbPz8wZx_DtTZRUmMaW7X0J37MpQbrABCeRD-ZlY7TCa7IliGXZISWgB7mn89mENHWnEB-1FyyUqH5XS4kTtG7XEY-bx3nlxQybtqrYFhroVUsxuXzsrTax0OmdZH07Gyi3K3Diszipu4QejSpdN-pVjvS3jUCFyI-dW3IALKEompe4zAuZ0Aux-yuEz4TxJDOGFVYry4F0OgNiFtlLGsO6vPbFloMRPaU6e3YCTgVkRjQbugOjamsB_0URcwJpuZO4qDisV2_faCY72TG_P240mv0Ui4ywvHMcn5YWVIAABQ'

这样就可以获得对应的资源信息了

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Wed, 05 Sep 2018 03:09:26 GMT
Docker-Distribution-Api-Version: registry/2.0
Strict-Transport-Security: max-age=31536000
Transfer-Encoding: chunked

{
    "name": "library/nginx",
    "tags": [
        "1-alpine-perl",
        "1-alpine",
        "1-perl",
        "1.10-alpine",
        "1.10.0-alpine",
        "1.10.0",
        "1.10.1-alpine",
        "1.10.1",
        "1.10.2-alpine",
        "1.10.2",
        "1.10.3-alpine",
        "1.10.3",
        "1.10",
        "1.11-alpine",
        "1.11.0-alpine",
        "1.11.0",
        "1.11.1-alpine",
        "1.11.1",
        "1.11.10-alpine",
        "1.11.10",
        "1.11.12-alpine",
        "1.11.12",
        "1.11.13-alpine",
        "1.11.13",
        "1.11.3-alpine",
        "1.11.3",
        "1.11.4-alpine",
        "1.11.4",
        "1.11.5-alpine",
        "1.11.5",
        "1.11.6-alpine",
        "1.11.6",
        "1.11.7-alpine",
        "1.11.7",
        "1.11.8-alpine",
        "1.11.8",
        "1.11.9-alpine",
        "1.11.9",
        "1.11",
        "1.12-alpine-perl",
        "1.12-alpine",
        "1.12-perl",
        "1.12.0-alpine-perl",
        "1.12.0-alpine",
        "1.12.0-perl",
        "1.12.0",
        "1.12.1-alpine-perl",
        "1.12.1-alpine",
        "1.12.1-perl",
        "1.12.1",
        "1.12.2-alpine-perl",
        "1.12.2-alpine",
        "1.12.2-perl",
        "1.12.2",
        "1.12",
        "1.13-alpine-perl",
        "1.13-alpine",
        "1.13-perl",
        "1.13.0-alpine-perl",
        "1.13.0-alpine",
        "1.13.0-perl",
        "1.13.0",
        "1.13.1-alpine-perl",
        "1.13.1-alpine",
        "1.13.1-perl",
        "1.13.1",
        "1.13.10-alpine-perl",
        "1.13.10-alpine",
        "1.13.10-perl",
        "1.13.10",
        "1.13.11-alpine-perl",
        "1.13.11-alpine",
        "1.13.11-perl",
        "1.13.11",
        "1.13.12-alpine-perl",
        "1.13.12-alpine",
        "1.13.12-perl",
        "1.13.12",
        "1.13.2-alpine-perl",
        "1.13.2-alpine",
        "1.13.2-perl",
        "1.13.2",
        "1.13.3-alpine-perl",
        "1.13.3-alpine",
        "1.13.3-perl",
        "1.13.3",
        "1.13.5-alpine-perl",
        "1.13.5-alpine",
        "1.13.5-perl",
        "1.13.5",
        "1.13.6-alpine-perl",
        "1.13.6-alpine",
        "1.13.6-perl",
        "1.13.6",
        "1.13.7-alpine-perl",
        "1.13.7-alpine",
        "1.13.7-perl",
        "1.13.7",
        "1.13.8-alpine-perl",
        "1.13.8-alpine",
        "1.13.8-perl",
        "1.13.8",
        "1.13.9-alpine-perl",
        "1.13.9-alpine",
        "1.13.9-perl",
        "1.13.9",
        "1.13",
        "1.14-alpine-perl",
        "1.14-alpine",
        "1.14-perl",
        "1.14.0-alpine-perl",
        "1.14.0-alpine",
        "1.14.0-perl",
        "1.14.0",
        "1.14",
        "1.15-alpine-perl",
        "1.15-alpine",
        "1.15-perl",
        "1.15.0-alpine-perl",
        "1.15.0-alpine",
        "1.15.0-perl",
        "1.15.0",
        "1.15.1-alpine-perl",
        "1.15.1-alpine",
        "1.15.1-perl",
        "1.15.1",
        "1.15.2-alpine-perl",
        "1.15.2-alpine",
        "1.15.2-perl",
        "1.15.2",
        "1.15.3-alpine-perl",
        "1.15.3-alpine",
        "1.15.3-perl",
        "1.15.3",
        "1.15",
        "1.7.1",
        "1.7.10",
        "1.7.11",
        "1.7.12",
        "1.7.5",
        "1.7.6",
        "1.7.7",
        "1.7.8",
        "1.7.9",
        "1.7",
        "1.8-alpine",
        "1.8.1-alpine",
        "1.8.1",
        "1.8",
        "1.9-alpine",
        "1.9.0",
        "1.9.1",
        "1.9.10",
        "1.9.11",
        "1.9.12",
        "1.9.14-alpine",
        "1.9.14",
        "1.9.15-alpine",
        "1.9.15",
        "1.9.2",
        "1.9.3",
        "1.9.4",
        "1.9.5",
        "1.9.6",
        "1.9.7",
        "1.9.8",
        "1.9.9",
        "1.9",
        "1",
        "alpine-perl",
        "alpine",
        "latest",
        "mainline-alpine-perl",
        "mainline-alpine",
        "mainline-perl",
        "mainline",
        "perl",
        "stable-alpine-perl",
        "stable-alpine",
        "stable-perl",
        "stable"
    ]
}

访问阿里云镜像信息

使用相同的方式可以调用阿里云的镜像服务相关API

参考

目录
相关文章
|
1月前
|
数据可视化 Linux API
如何在Linux使用docker部署Swagger Editor并实现无公网IP远程协同编辑API文档
如何在Linux使用docker部署Swagger Editor并实现无公网IP远程协同编辑API文档
|
3月前
|
数据可视化 Linux API
使用Docker安装部署Swagger Editor并远程访问编辑API文档
使用Docker安装部署Swagger Editor并远程访问编辑API文档
52 0
|
1月前
|
编解码 API Android开发
深入了解设备交互 API 如何改变我们的生活
深入了解设备交互 API 如何改变我们的生活
29 3
|
1月前
|
API
uni-app 25后端api开发和前后端交互(51-60)
uni-app 25后端api开发和前后端交互(51-60)
30 2
uni-app 25后端api开发和前后端交互(51-60)
|
1月前
|
中间件 API 数据库
uni-app 25后端api开发和前后端交互(1-50)
uni-app 25后端api开发和前后端交互(1-50)
101 0
uni-app 25后端api开发和前后端交互(1-50)
|
4月前
|
Kubernetes Shell API
DeepFace【部署 02】轻量级人脸识别和面部属性分析框架(实时分析+API+Docker部署+命令行接口)
DeepFace【部署 02】轻量级人脸识别和面部属性分析框架(实时分析+API+Docker部署+命令行接口)
101 0
|
4月前
|
数据可视化 Linux API
使用Docker安装部署Swagger Editor并远程访问编辑API文档
使用Docker安装部署Swagger Editor并远程访问编辑API文档
|
5月前
|
JSON 监控 测试技术
RESTful API设计与实现在员工行为监控系统中的数据交互接口(Go语言)
在现代企业环境中,对员工行为进行监控已经成为确保组织安全和合规性的重要手段。为了提高监控系统的效率和可靠性,自动化测试在系统开发过程中发挥着关键作用。本文将探讨在员工行为监控系统开发中采用JUnit进行自动化测试的实际应用,并通过代码示例演示其工作原理。
191 1
|
5月前
|
应用服务中间件 API nginx
通过 docker 学习 nginx,附全部配置及 API 测试,使用 apifox 直接打开
本篇文章以前端的视角,介绍下 nginx 的常见配置,并通过 docker 的方式学习 nginx,这保证所有实例配置都能正常运行。
|
6月前
|
存储 API
如何使用 SAP UI5 V2 ODataModel 模型 API 实现 deepCreate 的场景以及局限性
如何使用 SAP UI5 V2 ODataModel 模型 API 实现 deepCreate 的场景以及局限性
44 0