github.com/polarismesh/polaris@v1.17.8/auth/defaultauth/token.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package defaultauth 19 20 import ( 21 "crypto/aes" 22 "crypto/cipher" 23 "crypto/rand" 24 "encoding/base64" 25 "errors" 26 "fmt" 27 "io" 28 29 "github.com/google/uuid" 30 31 "github.com/polarismesh/polaris/common/model" 32 ) 33 34 // OperatorInfo 根据 token 解析出来的具体额外信息 35 type OperatorInfo struct { 36 37 // Origin 原始 token 字符串 38 Origin string 39 40 // OperatorID 当前 token 绑定的 用户/用户组 ID 41 OperatorID string 42 43 // OwnerID 当前用户/用户组对应的 owner 44 OwnerID string 45 46 // Role 如果当前是 user token 的话,该值才能有信息 47 Role model.UserRoleType 48 49 // IsUserToken 当前 token 是否是 user 的 token 50 IsUserToken bool 51 52 // Disable 标识用户 token 是否被禁用 53 Disable bool 54 55 // 是否属于匿名操作者 56 Anonymous bool 57 } 58 59 func newAnonymous() OperatorInfo { 60 return OperatorInfo{ 61 Origin: "", 62 OwnerID: "", 63 OperatorID: "__anonymous__", 64 Anonymous: true, 65 } 66 } 67 68 // IsEmptyOperator token 是否是一个空类型 69 func IsEmptyOperator(t OperatorInfo) bool { 70 return t.Origin == "" || t.Anonymous 71 } 72 73 // IsSubAccount 当前 token 对应的账户类型 74 func IsSubAccount(t OperatorInfo) bool { 75 return t.Role == model.SubAccountUserRole 76 } 77 78 func (t *OperatorInfo) String() string { 79 return fmt.Sprintf("operator-id=%s, owner=%s, role=%d, is-user=%v, disable=%v", 80 t.OperatorID, t.OwnerID, t.Role, t.IsUserToken, t.Disable) 81 } 82 83 const ( 84 // TokenPattern token 的格式 随机字符串::[uid/xxx | groupid/xxx] 85 TokenPattern string = "%s::%s" 86 // TokenSplit token 的分隔符 87 TokenSplit string = "::" 88 ) 89 90 // createUserToken Create a user token 91 func createUserToken(uid string) (string, error) { 92 return createToken(uid, "") 93 } 94 95 // createGroupToken Create user group token 96 func createGroupToken(gid string) (string, error) { 97 return createToken("", gid) 98 } 99 100 // createToken Determine what type of Token created according to the incoming parameters 101 func createToken(uid, gid string) (string, error) { 102 if uid == "" && gid == "" { 103 return "", errors.New("uid and groupid not be empty at the same time") 104 } 105 106 var val string 107 if uid == "" { 108 val = fmt.Sprintf("%s/%s", model.TokenForUserGroup, gid) 109 } else { 110 val = fmt.Sprintf("%s/%s", model.TokenForUser, uid) 111 } 112 113 token := fmt.Sprintf(TokenPattern, uuid.NewString()[8:16], val) 114 return encryptMessage([]byte(AuthOption.Salt), token) 115 } 116 117 // encryptMessage 对消息进行加密 118 func encryptMessage(key []byte, message string) (string, error) { 119 byteMsg := []byte(message) 120 block, err := aes.NewCipher(key) 121 if err != nil { 122 return "", fmt.Errorf("could not create new cipher: %v", err) 123 } 124 125 cipherText := make([]byte, aes.BlockSize+len(byteMsg)) 126 iv := cipherText[:aes.BlockSize] 127 if _, err = io.ReadFull(rand.Reader, iv); err != nil { 128 return "", fmt.Errorf("could not encrypt: %v", err) 129 } 130 131 stream := cipher.NewCFBEncrypter(block, iv) 132 stream.XORKeyStream(cipherText[aes.BlockSize:], byteMsg) 133 134 return base64.StdEncoding.EncodeToString(cipherText), nil 135 } 136 137 // decryptMessage 对消息进行解密 138 func decryptMessage(key []byte, message string) (string, error) { 139 cipherText, err := base64.StdEncoding.DecodeString(message) 140 if err != nil { 141 return "", fmt.Errorf("could not base64 decode: %v", err) 142 } 143 144 block, err := aes.NewCipher(key) 145 if err != nil { 146 return "", fmt.Errorf("could not create new cipher: %v", err) 147 } 148 149 if len(cipherText) < aes.BlockSize { 150 return "", fmt.Errorf("invalid ciphertext block size") 151 } 152 153 iv := cipherText[:aes.BlockSize] 154 cipherText = cipherText[aes.BlockSize:] 155 156 stream := cipher.NewCFBDecrypter(block, iv) 157 stream.XORKeyStream(cipherText, cipherText) 158 159 return string(cipherText), nil 160 }