プリズマリバースプロキシ

概要

しばらくの間接触したプリズマ、フレームは、いくつかの他のgraphqlインターフェイスで使用され、自動的に全体の間に生成され、そしてデータベースとの間の結合は、低プリズマ又はリッチ発生インタフェース、より便利に使用することです。

プリズマドキュメント:https://www.prisma.io/docs(この書き込みはバージョン1.34です)

なぜリバースプロキシプリズマ行います

プリズマサービス、インターフェイスが自動的に生成されますが、実際のプロジェクトでは、認証とアクセス制御のインターフェースの最も基本的なので、実際には、これらのインタフェースは、直接フロントにさらさ使用することは推奨されるものではない。でも、他のニーズがありますが、だけで自動的に生成することはできませんインターフェイスは、すべての機能を完了することができるようになります。

したがって、一般的なゲートウェイに、権限を認証を行い、通常(ゲートウェイと呼ばれることもある)層を再パッケージ、プリズマサービスを使用して、というように、唯一の正当な要求は最終プリズマサービスに。プリズマサービス自体を転送することができ準備ゲートウェイを容易にするために、輸出クライアントSDKは、現在4つのフォーマット(ジャバスクリプト、typescriptです、golang、フロー)をサポートし、JavaScriptとtypescriptですが、クライアントSDKの機能比較、golang機能弱くなる、試したことのない流れ。

使用golangクライアントSDKゲートウェイが再び適切な行動に直接作られたフロントgraphqlインターセプト要求、graphqlサーバ関連ライブラリーのgolangはとても完璧なのjs / TSを持っていません。だから、リバースプロキシモードを使用することを望んでいた見つけたときに私が書いた後リクエストのプリズマの内容がサービスに転送される。このように、プリズマを使用していないgolang、Javaの、C#の、および他の言語に加えて、ゲートウェイプリズマとして使用することができ、言語の制限を突破、クライアントSDKを生成

リバースプロキシ例(golangによって)

golang使用ジンのWebサービスゲートウェイフレームワークの一部として。認定をGIN-JWTミドルウェア・リバースプロキシと既製のフレームを使用していない権限]セクション。

全サンプルゲートウェイは:

  1. プリズマサービス(プリズマ+ MySQLは):このセクションでは、コンフィギュレーションテーブルとフィールドの例限り、レディドッカー画像を有します
  2. ゲートウェイ(golangジン):golangジン火災的服务

プリズマサービス

  1. prisma.yml

    endpoint: http://${env:PRISMA_HOST}:${env:PRISMA_PORT}/illuminant/${env:PRISMA_STAGE}
    datamodel: datamodel.prisma
    
    secret: ${env:PRISMA_MANAGEMENT_API_SECRET}
    
    generate:
      - generator: go-client
        output: ./
  2. .env

    PRISMA_HOST=localhost
    PRISMA_PORT=4466
    PRISMA_STAGE=dev
    PRISMA_MANAGEMENT_API_SECRET=secret-key
  3. datamodel.prisma

    type User {
      id: ID! @id
      name: String! @unique
      realName: String!
      password: String!
    
      createdAt: DateTime! @createdAt
      updatedAt: DateTime! @updatedAt
    }
  4. ドッキングウィンドウ-compose.yml

    version: '3'
    services:
      illuminant:
        image: prismagraphql/prisma:1.34
        # restart: always
        ports:
        - "4466:4466"
        environment:
          PRISMA_CONFIG: |
            port: 4466
            managementApiSecret: secret-key
            databases:
              default:
                connector: mysql
                host: mysql-db
                user: root
                password: prisma
                # rawAccess: true
                port: 3306
                migrations: true
    
      mysql-db:
        image: mysql:5.7
        # restart: always
        environment:
          MYSQL_ROOT_PASSWORD: prisma
        volumes:
          - mysql:/var/lib/mysql
    volumes:
      mysql: ~

ファイル上記と同じディレクトリ内のすべてのプリズマサービスと、彼らはMySQLを必要とするサービスのファイルを含めることができます

ゲートウェイサービス

ゲートウェイサービスは、キーだけでなく、部品の将来の拡張である。書き込むためのフレームワークを使用してgolangジン。

全体的なプロセス

  1. HTTPリクエスト
  2. ルートルート
  3. 認定チェック
  4. 権限のチェック
  5. プリズマ要求転送サービス(アップロード/ダウンロード、または需要の統計情報などを持っている場合は、このステップは通常、プリズマへのAPIを記述する必要が転送されます)
  6. リターンレスポンス

認証します

authMiddleware := controller.JwtMiddleware()
apiV1 := r.Group("/api/v1")

// no auth routes
apiV1.POST("/login", authMiddleware.LoginHandler)

// auth routes
authRoute := apiV1.Group("/")
authRoute.GET("/refresh_token", authMiddleware.RefreshHandler)
authRoute.Use(authMiddleware.MiddlewareFunc())
{
  // proxy prisma graphql
  authRoute.POST("/graphql", ReverseProxy())
}

/ API / V1 / graphql JWTの認証を満たしながら、アクセスすることができます。

リバースプロキシ

func ReverseProxy() gin.HandlerFunc {

  return func(c *gin.Context) {
    director := func(req *http.Request) {
      req.URL.Scheme = "http"
      req.URL.Host = primsa-host
      req.URL.Path = primsa-endpoint
      delete(req.Header, "Authorization")
      req.Header["Authorization"] = []string{"Bearer " + primsa-token}

    }

    // 解析出 body 中的内容, 进行权限检查
    body, err := c.GetRawData()
    if err != nil {
      fmt.Println(err)
    }

    // 对 body 进行权限 check
    // 权限 Check, 解析出 graphql 中请求的函数, 然后判断是否有权限
    // 目前的方式是根据请求中函数的名称来判断权限, 也就是只能对表的 CURD 权限进行判断, 对于表中的字段权限还无法检查
    // 如果权限检查没有通过, 直接返回, 不要再进行下面的请求转发

    // 将 body 反序列化回请求中, 转发给 prisma 服务
    c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))

    proxy := &httputil.ReverseProxy{Director: director}
    proxy.ModifyResponse = controller.RewriteBody
    proxy.ServeHTTP(c.Writer, c.Request)
  }
}

技量

// 检查权限
func CheckAuthority(body []byte, userId string) bool {
        var bodyJson struct {
                Query string `json:"query"`
        }
        log := logger.GetLogger()
        if err := json.Unmarshal(body, &bodyJson); err != nil {
                log.Error("body convert to json error: %s", err.Error())
                return false
        }

        graphqlFunc := RegrexGraphqlFunc(bodyJson.Query)
        if graphqlFunc == "" {
                return false
        }

        // 这里的 userId 是从 jwt 中解析出来的, 然后再判断用户是否有权限

        if graphqlFunc == "users" {
                return false
        }
        return true
}

// 匹配 graphql 请求的函数
func RegrexGraphqlFunc(graphqlReq string) string {
        graphqlReq = strings.TrimSpace(graphqlReq)
        // reg examples:
        // { users {id} }
        // { users(where: {}) {id} }
        // mutation{ user(data: {}) {id} }
        var regStrs = []string{
                `^\{\s*(\w+)\s*\{.*\}\s*\}$`,
                `^\{\s*(\w+)\s*\(.*\)\s*\{.*\}\s*\}$`,
                `^mutation\s*\{\s*(\w+)\s*\(.*\)\s*\{.*\}\s*\}$`,
        }

        for _, regStr := range regStrs {
                r := regexp.MustCompile(regStr)
                matches := r.FindStringSubmatch(graphqlReq)
                if matches != nil && len(matches) > 1 {
                        return matches[1]
                }
        }

        return ""
}

ここでの権限チェックのアイデアが。最終的なコードではなく、達成された
だけの一時的な解決策ではなく、最良の方法は機能要求にマッチする正規表現を特徴とする請求方法、
最善の方法は、ライブラリgolangを解析し、対応するgraphqlする必要があります構造は、要求を解析され、その許諾を持っているときに解析された機能を決定します

概要

後の場合はクライアントSDK、またはゲートウェイベースのクライアントSDKを向上した後、プリズマクライアントSDKの制限を打破するためには、リバースプロキシモードを使用することで、より信頼性の高い開発します。

おすすめ

転載: www.cnblogs.com/wang_yb/p/11411840.html