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  }