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 }