github.com/godaddy-x/freego@v1.0.156/utils/jwt/subject.go (about)

     1  package jwt
     2  
     3  /**
     4   * @author shadow
     5   * @createby 2018.12.13
     6   */
     7  
     8  import (
     9  	"github.com/godaddy-x/freego/utils"
    10  	"strings"
    11  )
    12  
    13  const (
    14  	JWT          = "JWT"
    15  	HS256        = "HS256"
    16  	SHA256       = "SHA256"
    17  	MD5          = "MD5"
    18  	AES          = "AES"
    19  	RSA          = "RSA"
    20  	FIVE_MINUTES = int64(300)
    21  	TWO_WEEK     = int64(1209600)
    22  )
    23  
    24  type Subject struct {
    25  	Header       *Header
    26  	Payload      *Payload
    27  	tokenBytes   []byte
    28  	payloadBytes []byte
    29  }
    30  
    31  type JwtConfig struct {
    32  	TokenKey string
    33  	TokenAlg string
    34  	TokenTyp string
    35  	TokenExp int64
    36  }
    37  
    38  type Header struct {
    39  	Alg string `json:"alg"`
    40  	Typ string `json:"typ"`
    41  }
    42  
    43  type Payload struct {
    44  	Sub string `json:"sub"` // 用户主体
    45  	Aud string `json:"aud"` // 接收token主体
    46  	Iss string `json:"iss"` // 签发token主体
    47  	Iat int64  `json:"iat"` // 授权token时间
    48  	Exp int64  `json:"exp"` // 授权token过期时间
    49  	Dev string `json:"dev"` // 设备类型,web/app
    50  	Jti string `json:"jti"` // 唯一身份标识,主要用来作为一次性token,从而回避重放攻击
    51  	Ext string `json:"ext"` // 扩展信息
    52  }
    53  
    54  func (self *Subject) AddHeader(config JwtConfig) *Subject {
    55  	self.Header = &Header{Alg: config.TokenAlg, Typ: config.TokenTyp}
    56  	return self
    57  }
    58  
    59  func (self *Subject) Create(sub string) *Subject {
    60  	self.Payload = &Payload{
    61  		Sub: sub,
    62  		Exp: utils.UnixSecond() + TWO_WEEK,
    63  		Jti: utils.MD5(utils.GetUUID(), true),
    64  	}
    65  	return self
    66  }
    67  
    68  // exp seconds
    69  func (self *Subject) Expired(exp int64) *Subject {
    70  	if exp > 0 {
    71  		if self.Payload.Iat > 0 {
    72  			self.Payload.Exp = self.Payload.Iat + exp
    73  		} else {
    74  			self.Payload.Exp = utils.UnixSecond() + exp
    75  		}
    76  	}
    77  	return self
    78  }
    79  
    80  func (self *Subject) Dev(dev string) *Subject {
    81  	if len(dev) > 0 {
    82  		self.Payload.Dev = dev
    83  	}
    84  	return self
    85  }
    86  
    87  func (self *Subject) Iss(iss string) *Subject {
    88  	if len(iss) > 0 {
    89  		self.Payload.Iss = iss
    90  	}
    91  	return self
    92  }
    93  
    94  func (self *Subject) Aud(aud string) *Subject {
    95  	if len(aud) > 0 {
    96  		self.Payload.Aud = aud
    97  	}
    98  	return self
    99  }
   100  
   101  func (self *Subject) Generate(config JwtConfig) string {
   102  	self.AddHeader(config)
   103  	header, err := utils.ToJsonBase64(self.Header)
   104  	if err != nil {
   105  		return ""
   106  	}
   107  	if config.TokenExp > 0 {
   108  		if self.Payload.Iat > 0 {
   109  			self.Payload.Exp = self.Payload.Iat + config.TokenExp
   110  		} else {
   111  			self.Payload.Exp = utils.UnixSecond() + config.TokenExp
   112  		}
   113  	}
   114  	payload, err := utils.ToJsonBase64(self.Payload)
   115  	if err != nil {
   116  		return ""
   117  	}
   118  	part1 := utils.AddStr(header, ".", payload)
   119  	return part1 + "." + self.Signature(part1, config.TokenKey)
   120  }
   121  
   122  func (self *Subject) Signature(text, key string) string {
   123  	return utils.HMAC_SHA256(text, utils.AddStr(utils.GetLocalSecretKey(), key), true)
   124  }
   125  
   126  func (self *Subject) GetTokenSecret(token, secret string) string {
   127  	key := utils.GetLocalTokenSecretKey()
   128  	key2 := utils.HMAC_SHA256(utils.AddStr(utils.SHA256(token, true), utils.MD5(utils.GetLocalSecretKey()), true), secret, true)
   129  	keyBs := utils.Str2Bytes(key)
   130  	key2Bs := utils.Str2Bytes(key2)
   131  	secBs := make([]byte, 64)
   132  	copy(secBs, key2Bs[0:15])
   133  	copy(secBs[15:], keyBs[3:13])
   134  	copy(secBs[25:], key2Bs[15:30])
   135  	copy(secBs[40:], keyBs[10:20])
   136  	copy(secBs[50:], key2Bs[30:])
   137  	return utils.Bytes2Str(secBs)
   138  }
   139  
   140  func (self *Subject) Verify(token, key string, decode bool) error {
   141  	if len(token) == 0 {
   142  		return utils.Error("token is nil")
   143  	}
   144  	part := strings.Split(token, ".")
   145  	if part == nil || len(part) != 3 {
   146  		return utils.Error("token part length invalid")
   147  	}
   148  	part0 := part[0]
   149  	part1 := part[1]
   150  	part2 := part[2]
   151  	if self.Signature(utils.AddStr(part0, ".", part1), key) != part2 {
   152  		return utils.Error("token signature invalid")
   153  	}
   154  	b64 := utils.Base64Decode(part1)
   155  	if b64 == nil || len(b64) == 0 {
   156  		return utils.Error("token part base64 data decode failed")
   157  	}
   158  	if int64(utils.GetJsonInt(b64, "exp")) <= utils.UnixSecond() {
   159  		return utils.Error("token expired or invalid")
   160  	}
   161  	if !decode {
   162  		return nil
   163  	}
   164  	if self.Payload == nil {
   165  		self.Payload = &Payload{}
   166  	}
   167  	self.payloadBytes = b64
   168  	self.Payload.Sub = self.getStringValue("sub")
   169  	return nil
   170  }
   171  
   172  func (self *Subject) CheckReady() bool {
   173  	if self.Payload == nil || len(self.Payload.Sub) == 0 {
   174  		return false
   175  	}
   176  	return true
   177  }
   178  
   179  func (self *Subject) ResetTokenBytes(b []byte) {
   180  	if b == nil && len(self.tokenBytes) == 0 {
   181  		return
   182  	}
   183  	self.tokenBytes = nil
   184  	if b == nil {
   185  		return
   186  	}
   187  	self.tokenBytes = b
   188  }
   189  
   190  func (self *Subject) ResetPayloadBytes(b []byte) {
   191  	if b == nil && len(self.payloadBytes) == 0 {
   192  		return
   193  	}
   194  	self.payloadBytes = nil
   195  	if b == nil {
   196  		return
   197  	}
   198  	self.payloadBytes = b
   199  }
   200  
   201  func (self *Subject) GetRawBytes() []byte {
   202  	if len(self.tokenBytes) == 0 {
   203  		return []byte{}
   204  	}
   205  	return self.tokenBytes
   206  }
   207  
   208  func (self *Subject) GetSub() string {
   209  	if self.Payload == nil {
   210  		self.Payload = &Payload{}
   211  	}
   212  	if len(self.Payload.Sub) == 0 {
   213  		self.Payload.Sub = self.getStringValue("sub")
   214  	}
   215  	return self.Payload.Sub
   216  }
   217  
   218  func (self *Subject) GetIss() string {
   219  	return self.getStringValue("iss")
   220  }
   221  
   222  func (self *Subject) GetAud() string {
   223  	return self.getStringValue("aud")
   224  }
   225  
   226  func (self *Subject) GetIat() int64 {
   227  	return self.getInt64Value("iat")
   228  }
   229  
   230  func (self *Subject) GetExp() int64 {
   231  	return self.getInt64Value("exp")
   232  }
   233  
   234  func (self *Subject) GetDev() string {
   235  	return self.getStringValue("dev")
   236  }
   237  
   238  func (self *Subject) GetJti() string {
   239  	return self.getStringValue("jti")
   240  }
   241  
   242  func (self *Subject) GetExt() string {
   243  	return self.getStringValue("ext")
   244  }
   245  
   246  func (self *Subject) getStringValue(k string) string {
   247  	if len(self.payloadBytes) == 0 {
   248  		return ""
   249  	}
   250  	return utils.GetJsonString(self.payloadBytes, k)
   251  }
   252  
   253  func (self *Subject) getInt64Value(k string) int64 {
   254  	if len(self.payloadBytes) == 0 {
   255  		return 0
   256  	}
   257  	return utils.GetJsonInt64(self.payloadBytes, k)
   258  }
   259  
   260  // 获取token的私钥
   261  func GetTokenSecret(token, secret string) string {
   262  	if len(token) == 0 {
   263  		return ""
   264  	}
   265  	subject := &Subject{}
   266  	return subject.GetTokenSecret(token, secret)
   267  }