sun-pc 4 mesiacov pred
rodič
commit
8a204e1f0a
11 zmenil súbory, kde vykonal 171 pridanie a 32 odobranie
  1. 1 0
      src/Dockerfile
  2. 14 4
      src/api/api.go
  3. 7 20
      src/api/controller.go
  4. 29 0
      src/api/getToken.go
  5. 3 0
      src/api/router.go
  6. 7 1
      src/app.yaml
  7. 11 0
      src/conf/app.go
  8. 6 3
      src/go.mod
  9. 11 4
      src/go.sum
  10. 53 0
      src/middleware/auth.go
  11. 29 0
      src/token_jwt_key.pem

+ 1 - 0
src/Dockerfile

@@ -6,6 +6,7 @@ RUN mkdir -p /root/projects
 WORKDIR /root/projects
 
 ADD ./app.yaml ./app.yaml
+ADD ./token_jwt_key.pem ./token_jwt_key.pem
 ADD ./moutai ./moutai
 
 EXPOSE 3002

+ 14 - 4
src/api/api.go

@@ -6,7 +6,10 @@ import (
 	"moutai/conf"
 	"moutai/db"
 	"moutai/db/repo"
+	"moutai/middleware"
+	"os"
 
+	"github.com/casdoor/casdoor-go-sdk/casdoorsdk"
 	"github.com/gin-contrib/cors"
 	"github.com/gin-gonic/gin"
 	"github.com/go-redis/redis/v8"
@@ -26,8 +29,9 @@ func (svc *Service) Run() {
 }
 
 type ApiSession struct {
-	Svc  *Service
-	User *JWTUser
+	Svc *Service
+	// User *JWTUser
+	User *casdoorsdk.Claims
 }
 
 func (api *ApiSession) CreateRepoCtx() *repo.RepoSession {
@@ -38,6 +42,12 @@ func (api *ApiSession) CreateRepoCtx() *repo.RepoSession {
 }
 
 func NewHttpService(app *conf.AppConf, dbMongo *db.MongoDB, redisClient *redis.Client) *Service {
+	authConf := app.Auth
+	pemByte, err := os.ReadFile(authConf.Certificate)
+	if err != nil {
+		panic(err)
+	}
+	casdoorsdk.InitConfig(authConf.Endpoint, authConf.ClientId, authConf.ClientSecret, string(pemByte), authConf.OrganizationName, authConf.ApplicationName)
 
 	engine := gin.Default()
 
@@ -87,12 +97,12 @@ func (g GinRouter) POST(path string, httpHandler Handler) {
 
 // GETJWT http Get 请求
 func (g GinRouter) GETJWT(path string, httpHandler JWTHander) {
-	g.group.GET(path, g.svc.JWT.MiddleFunc(), ResultJWTWrapper(httpHandler, g.svc))
+	g.group.GET(path, middleware.CasdoorAuthMiddleware(), ResultJWTWrapper(httpHandler, g.svc))
 }
 
 // POSTJWT http POST 请求
 func (g GinRouter) POSTJWT(path string, httpHandler JWTHander) {
-	g.group.POST(path, g.svc.JWT.MiddleFunc(), ResultJWTWrapper(httpHandler, g.svc))
+	g.group.POST(path, middleware.CasdoorAuthMiddleware(), ResultJWTWrapper(httpHandler, g.svc))
 }
 
 // DeleteJWT http POST 请求

+ 7 - 20
src/api/controller.go

@@ -10,7 +10,7 @@ import (
 	"strconv"
 	"strings"
 
-	jwt "github.com/appleboy/gin-jwt/v2"
+	"github.com/casdoor/casdoor-go-sdk/casdoorsdk"
 	"github.com/gin-gonic/gin"
 )
 
@@ -74,19 +74,13 @@ func ResultJWTWrapper(handle JWTHander, svc *Service) gin.HandlerFunc {
 			}
 		}()
 
-		claims := jwt.ExtractClaims(c)
+		claims, _ := c.Get("casdoor_user")
 
-		var usr *JWTUser
+		user := claims.(*casdoorsdk.Claims)
 
-		if claims["id"] != nil {
-			fmt.Printf("%#v\n", claims)
-			id := claims["id"].(string)
-
-			usr = &JWTUser{ID: id}
-		}
 		var apis = &ApiSession{
 			Svc:  svc,
-			User: usr,
+			User: user,
 		}
 		data, err := handle(c, apis)
 
@@ -125,21 +119,14 @@ func ResultJWTWrapperKey(handle JWTHander, svc *Service, keys []string) gin.Hand
 			}
 		}()
 
-		claims := jwt.ExtractClaims(c)
-
-		var usr *JWTUser
+		claims, _ := c.Get("casdoor_user")
 
-		if claims["id"] != nil {
-			id := claims["id"].(string)
-
-			usr = &JWTUser{ID: id}
-		}
+		user := claims.(*casdoorsdk.Claims)
 
 		var apis = &ApiSession{
 			Svc:  svc,
-			User: usr,
+			User: user,
 		}
-
 		data, err := handle(c, apis)
 
 		if err != nil {

+ 29 - 0
src/api/getToken.go

@@ -0,0 +1,29 @@
+package api
+
+import (
+	"fmt"
+
+	"github.com/casdoor/casdoor-go-sdk/casdoorsdk"
+	"github.com/gin-gonic/gin"
+)
+
+func getToken(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	token, err := casdoorsdk.GetOAuthToken(c.Query("code"), c.Query("state"))
+	if err != nil {
+		fmt.Println(err)
+		return err, nil
+	}
+
+	fmt.Println(token.AccessToken)
+	claims, err := casdoorsdk.ParseJwtToken(token.AccessToken)
+	if err != nil {
+		fmt.Println(err)
+		return err, nil
+	}
+	fmt.Println(claims)
+	// c.Redirect(http.StatusFound, "https://auth.3dqueen.cloud")
+
+	claims.AccessToken = token.AccessToken
+	return claims, nil
+}

+ 3 - 0
src/api/router.go

@@ -99,6 +99,9 @@ func RegRouters(svc *Service) {
 	// 点击次数
 	moutai.GET("/click", Clicks)
 
+	// 获取token
+	moutai.GET("/getToken", getToken)
+
 }
 
 func Logger() gin.HandlerFunc {

+ 7 - 1
src/app.yaml

@@ -18,4 +18,10 @@ log:
 nats:
   url: nats://127.0.0.1:14223
 
-
+Auth:
+  endpoint: https://auth.3dqueen.cloud
+  clientId:	e537ce727be61ad962d0
+  clientSecret: 2beafa72f3b73f7bbb8a54708d579c41c24c9bef
+  certificate: token_jwt_key.pem
+  organizationName:	cmf
+  applicationName: cmf-editor-admin

+ 11 - 0
src/conf/app.go

@@ -48,6 +48,17 @@ type AppConf struct {
 		MattingRequestStreamTopic string
 		MattingResultStreamTopic  string
 	}
+
+	// casdoor认证配置
+	Auth struct {
+		Endpoint     string
+		ClientId     string
+		ClientSecret string
+
+		Certificate      string
+		OrganizationName string
+		ApplicationName  string
+	}
 }
 
 func LoadConfFile(filepath string) (*AppConf, error) {

+ 6 - 3
src/go.mod

@@ -4,6 +4,7 @@ go 1.21
 
 require (
 	github.com/appleboy/gin-jwt/v2 v2.7.0
+	github.com/casdoor/casdoor-go-sdk v1.3.0
 	github.com/gin-contrib/cors v1.3.1
 	github.com/gin-gonic/gin v1.7.4
 	github.com/go-redis/redis/v8 v8.11.5
@@ -24,9 +25,9 @@ require (
 	github.com/go-playground/locales v0.13.0 // indirect
 	github.com/go-playground/universal-translator v0.17.0 // indirect
 	github.com/go-playground/validator/v10 v10.4.1 // indirect
-	github.com/golang-jwt/jwt/v4 v4.1.0 // indirect
+	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
 	github.com/golang-migrate/migrate/v4 v4.15.2 // indirect
-	github.com/golang/protobuf v1.5.2 // indirect
+	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/golang/snappy v0.0.4 // indirect
 	github.com/hashicorp/errwrap v1.1.0 // indirect
 	github.com/hashicorp/go-multierror v1.1.1 // indirect
@@ -62,10 +63,12 @@ require (
 	go.uber.org/multierr v1.6.0 // indirect
 	golang.org/x/crypto v0.19.0 // indirect
 	golang.org/x/net v0.21.0 // indirect
+	golang.org/x/oauth2 v0.13.0 // indirect
 	golang.org/x/sync v0.1.0 // indirect
 	golang.org/x/sys v0.17.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
-	google.golang.org/protobuf v1.28.1 // indirect
+	google.golang.org/appengine v1.6.7 // indirect
+	google.golang.org/protobuf v1.31.0 // indirect
 	gopkg.in/ini.v1 v1.66.6 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 )

+ 11 - 4
src/go.sum

@@ -179,6 +179,8 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2
 github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
 github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
 github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
+github.com/casdoor/casdoor-go-sdk v1.3.0 h1:iUZKsrNUkhtAoyitFIFw3e6TchctAdoxmVgLDtNAgpc=
+github.com/casdoor/casdoor-go-sdk v1.3.0/go.mod h1:cMnkCQJgMYpgAlgEx8reSt1AVaDIQLcJ1zk5pzBaz+4=
 github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
 github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
 github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
@@ -527,8 +529,9 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
-github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0=
 github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
+github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
+github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-migrate/migrate/v4 v4.15.2 h1:vU+M05vs6jWHKDdmE1Ecwj0BznygFc4QsdRe2E/L7kc=
 github.com/golang-migrate/migrate/v4 v4.15.2/go.mod h1:f2toGLkYqD3JH+Todi4aZ2ZdbeUNx4sIwiOK96rE9Lw=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
@@ -566,8 +569,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
-github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -1413,6 +1417,8 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ
 golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
+golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1719,6 +1725,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
 google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
 google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
@@ -1840,8 +1847,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
-google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

+ 53 - 0
src/middleware/auth.go

@@ -0,0 +1,53 @@
+package middleware
+
+import (
+	"net/http"
+	"strings"
+	"time"
+
+	"github.com/casdoor/casdoor-go-sdk/casdoorsdk"
+	"github.com/gin-gonic/gin"
+)
+
+// Casdoor 中间件,用于验证请求中的 token
+func CasdoorAuthMiddleware() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		// 从请求头中获取 Authorization token
+		authHeader := c.GetHeader("Authorization")
+		if authHeader == "" {
+			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Authorization header is missing"})
+			return
+		}
+
+		// 提取 token,格式一般为 "Bearer <token>"
+		parts := strings.SplitN(authHeader, " ", 2)
+		if len(parts) != 2 || parts[0] != "Bearer" {
+			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid Authorization header format"})
+			return
+		}
+
+		token := parts[1]
+		if token == "" {
+			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Token is missing"})
+			return
+		}
+
+		// 验证 token
+		claims, err := casdoorsdk.ParseJwtToken(token)
+		if err != nil {
+			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token: " + err.Error()})
+			return
+		}
+		// 检查 token 是否过期
+		if claims.ExpiresAt.Compare(time.Now()) < 0 {
+			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Token has expired"})
+			return
+		}
+
+		// 将用户信息存储在上下文中,以便后续使用
+		c.Set("casdoor_user", claims)
+
+		// 继续处理请求
+		c.Next()
+	}
+}

+ 29 - 0
src/token_jwt_key.pem

@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIE3TCCAsWgAwIBAgIDAeJAMA0GCSqGSIb3DQEBCwUAMCgxDjAMBgNVBAoTBWFk
+bWluMRYwFAYDVQQDEw1jZXJ0LWJ1aWx0LWluMB4XDTI0MTEyNzAzMjgwNloXDTQ0
+MTEyNzAzMjgwNlowKDEOMAwGA1UEChMFYWRtaW4xFjAUBgNVBAMTDWNlcnQtYnVp
+bHQtaW4wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDMtMkb81XOZR1t
+t06uSHn6dlyclL/ZJojD3ZGNellKtTMTiy9Aud50Ig2EbJTLlpRbZM84lcFPsNh+
+HlWGwsdluNymLwTqek5aC3Ks0Qyb8gafZuXA+sSIeObDaDqbYKh8yxaMqEN344O0
+iKyM1KRX4y2lyPWZkfHXg/mFGxfK0OeM7bHysVIM4jizlrED4dpy1AvbJSKGHnfl
+KdNGWkedwP219kWq9f2InVi5XThxqHOyqT0dOOhq9s9T5NQwiMqp5lQDNN49h413
+9Cj0MYquEFlr5RHi/qrPTqBvPiXVAt7yfoFm0IKkjuJP4QKqvcbPBvl+rj9WrIQn
+iV+hTutEK2PQwzANcFZm+VgA150OEaTkxLwwiTPRCVEmGxcI5i8PBZv1HI0xjO6v
+8+wEt8TlySeEbob+uAECYrFhNUN2Ag7vfoegVzwy0RYqvaZJMWGXigirjSHGo4AH
+wvtOreOPn/AFVTlMMBUvM8mMtQf7jH4ZA2jXPbuMj7f9L0lZ88NVlL1RyA6FStyQ
+ZfBKwyxfsdV4ez5xZZApXlqskXiYnXCPmQ0IdrJaU51ZyqmiBA3uS5R0L0+SFUEJ
+GGy4J8t/MIxOltQrE/6Uwk3RG9ZO4JA4E5BHCQ9YEWjl98OWhvD3Z1o/wU240+Ut
+TMYNGo6jYuZ0aLSo4ZPqiOfCbepB/QIDAQABoxAwDjAMBgNVHRMBAf8EAjAAMA0G
+CSqGSIb3DQEBCwUAA4ICAQAp2xTcGQEZe6IjyBhHy1YBYXR4bZEYeqkK1uKsnj4a
+LQepMuTprSixkY+GB1ic5rW01RHJ+GuFepISKzPxRtNEgmLiNSOG/NnH3Sg0Ehl2
+miAA342UFFFFKgIYZeATI4Cgp5sZV0skUV776pFv0w0edr0cIChc/BieTpw8mK50
+GSkS/KGny+9KqeN1DSN2fJFdyN1wE7RsfC4zdu9DWOMun3wlruxmwDMJ+4sJgsbg
+LP5w1Lk9KjRJCegX7qf/5ow9iXrZwz+YCew+OfVtBrrnq3criqWMhe1aLj3noDZ5
+z0yB1qkz2IR2ETVSge5obBairhwZ6B2ffnYuS62O6OTkEVtmA2gqj9IaWh9QuwAV
+M4Dwq7pE3DX6tP3Y9BsqyNPg3MpyCe3W99QDKaxWHp1ELYUdyZmSmwvvx9bZw1Vg
+fL9jV4uyqdpoQepBqzyO9K37ShOfxMHj/BGu+IWoUkXdSx7lV8ZqISUSGX4RLPpB
+DJoJnWkrJZlR+AhiDkzeKfLIXvqiq5T5CeAR0wrXZb78H9JhxsVxc1yE2mUQrNVb
+usPDoKhFz5Tixa48UAtEJ9E+Ayo9ybeInoXPoRVmdOb2Jbk5DxDjj+9FLSi0Q00G
+A1ovAZwNA9/S/pIMHk27W2h//NPE/OVggdWBH+ykvsGFAqIddqI5dR+zlRs48Zmv
+KQ==
+-----END CERTIFICATE-----