wmj-test/main.go

193 lines
4.6 KiB
Go

package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"embed"
"encoding/base64"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v4"
log "github.com/sirupsen/logrus"
"io/fs"
m "k8s-manager/src"
"net/http"
"os"
"strings"
)
//go:embed template/* static/*
var f embed.FS
var jwtKey string
var aseKey string
func main() {
m.InitClient()
jwtKey = os.Getenv("JWT_KEY")
aseKey = os.Getenv("ASE_KEY")
if jwtKey == "" {
panic("No jwt key")
}
if aseKey == "" {
panic("No ase key")
}
r := gin.Default()
fp, _ := fs.Sub(f, "static")
r.StaticFS("/static", http.FS(fp))
r.GET("/index", m.JWTAuthMiddleware, func(c *gin.Context) {
c.FileFromFS("/template/app_view.html", http.FS(f))
})
r.GET("/apps", m.JWTAuthMiddleware, m.GetAppsController)
r.POST("/app", m.JWTAuthMiddleware, m.CreateUpdateDeleteApp)
r.PUT("/app", m.JWTAuthMiddleware, m.CreateUpdateDeleteApp)
r.DELETE("/app", m.JWTAuthMiddleware, m.CreateUpdateDeleteApp)
r.POST("/dep", m.JWTAuthMiddleware, m.CreateDeleteDeployment)
r.DELETE("/dep", m.JWTAuthMiddleware, m.CreateDeleteDeployment)
r.GET("/login", Test)
r.Any("/test_token", TestToken)
r.GET("/username", m.JWTAuthMiddleware, m.GetUsername)
err := r.Run(":8000")
if err != nil {
log.Fatal(err)
}
}
type CGJWTClaim struct {
jwt.RegisteredClaims
Userid string
}
func ParseCGToken(token string) (string, error) {
token = strings.ReplaceAll(token, "-", "+")
token = strings.ReplaceAll(token, "_", "/")
token = token + []string{"", "===", "==", "="}[len(token)%4]
aesEncrypt, err := base64.StdEncoding.DecodeString(token)
if err != nil {
log.WithError(err).Error("Parse CG Token 1")
return "", err
}
jwtString := AesDecryptECB(aesEncrypt, []byte(aseKey))
jwtResult, err := jwt.ParseWithClaims(string(jwtString), &CGJWTClaim{}, func(token *jwt.Token) (i interface{}, err error) {
return []byte(jwtKey), nil
// return hmac.New(sha256.New, []byte(jwtKey)), nil
})
if err != nil {
log.WithError(err).Error("Parse CG Token 2")
return "", err
}
if claims, ok := jwtResult.Claims.(*CGJWTClaim); ok && jwtResult.Valid { // 校验token
return claims.Userid, nil
}
return "", errors.New("jwt parse error")
}
func generateKey(key []byte) (genKey []byte) {
genKey = make([]byte, 16)
copy(genKey, key)
for i := 16; i < len(key); {
for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
genKey[j] ^= key[i]
}
}
return genKey
}
func AesDecryptECB(encrypted []byte, key []byte) (decrypted []byte) {
sh := sha1.New()
sh.Write(key)
realKey := sh.Sum(nil)
c, err := aes.NewCipher(realKey[:16])
if err != nil {
log.WithError(err).Error(AesDecryptECB)
}
decrypted = make([]byte, len(encrypted))
//
for bs, be := 0, c.BlockSize(); bs < len(encrypted); bs, be = bs+c.BlockSize(), be+c.BlockSize() {
c.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
}
func AesDecrypt(data []byte, key []byte) ([]byte, error) {
sh := sha1.New()
sh.Write(key)
realKey := sh.Sum(nil)
fmt.Println(string(realKey))
block, err := aes.NewCipher(realKey[:16])
if err != nil {
log.WithError(err).Error("AesDecrypt 1")
return nil, err
}
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
crypted := make([]byte, len(data))
blockMode.CryptBlocks(crypted, data)
if err != nil {
log.WithError(err).Error("AesDecrypt 2")
return nil, err
}
return crypted, nil
}
func Test(c *gin.Context) {
username := c.Request.URL.Query().Get("username")
var err error
if username == "" {
username, err = ParseCGToken(c.Request.URL.Query().Get("cgtoken"))
}
if username == "" || err != nil {
c.JSON(http.StatusNotFound, gin.H{
"code": http.StatusNotFound,
"msg": "user name error",
})
} else {
token, err := m.GenerateToken(username)
if err != nil {
log.Error(err)
c.Abort()
return
}
c.SetCookie("Authorization", "Bearer "+token, 0, "", "", false, false)
c.Header("Authorization", "Bearer "+token)
c.Header("Cache-Control", "no-store")
redirectUrl := ""
if os.Getenv("URL_PREFIX") == "" {
redirectUrl = "/index"
} else {
redirectUrl = fmt.Sprintf("/%s/index", os.Getenv("URL_PREFIX"))
}
c.Redirect(http.StatusTemporaryRedirect, redirectUrl)
}
}
func TestToken(c *gin.Context) {
token := c.Request.URL.Query().Get("cgtoken")
if token == "" {
c.JSON(http.StatusForbidden, gin.H{"msg": "No token"})
return
}
username, err := ParseCGToken(token)
if err != nil {
c.JSON(http.StatusForbidden, gin.H{"msg": "token error"})
return
}
c.JSON(http.StatusOK, gin.H{"msg": "ok", "username": username})
}