用go封裝一下臨時token 本篇為用go設計開發一個自己的輕量級登錄庫/框架吧 的臨時token篇,會講講臨時token的實現,給庫/框架增加新的功能。 Github:https://github.com/weloe/token-go 臨時token也算是比較常見的業務,例如登錄驗證碼信息,邀請鏈 ...
用go封裝一下臨時token
本篇為用go設計開發一個自己的輕量級登錄庫/框架吧 的臨時token篇,會講講臨時token的實現,給庫/框架增加新的功能。
Github:https://github.com/weloe/token-go
臨時token也算是比較常見的業務,例如登錄驗證碼信息,邀請鏈接等等,都屬於臨時token的範疇。
在token-go中同樣使用Adapter組件進行了簡單的封裝。
封裝思路
對於一個登錄驗證碼,我們需要有創建,有效期,需要解析,需要能刪除的功能。
因此,我們需要創建臨時token,獲取臨時token有效期,解析臨時token,刪除臨時token這幾個方法。
而臨時token會跟業務信息做關聯,比如這個臨時token是用於驗證碼服務或是用於邀請服務他們是互相隔離的,因此在存儲的時候我們需要一個service參數做區分,我們存儲為k,v結構,存儲的key結構為: "token-go:" + "temp-token" + ":temp:" + service + ":" + token
,存儲的value即為設定的對應的值。
最後決定出幾個api
// Temp token api
CreateTempToken(token string, service string, value string, timeout int64) (string, error)
CreateTempTokenByStyle(style string, service string, value string, timeout int64) (string, error)
GetTempTokenTimeout(service string, tempToken string) int64
ParseTempToken(service string, tempToken string) string
DeleteTempToken(service string, tempToken string) error
代碼實現
創建臨時token
這裡我們提供了兩個方法,一個用於根據style使用內置創建token的函數創建token,另一個用於直接由開發者生成token再傳入。創建token則是Adapter對信息進行存儲。
通過指定style創建
func (e *Enforcer) CreateTempTokenByStyle(style string, service string, value string, timeout int64) (string, error) {
token, err := e.generateFunc.Exec(style)
if err != nil {
return "", err
}
err = e.setTempToken(service, token, value, timeout)
if err != nil {
return "", err
}
return token, nil
}
指定token創建。
func (e *Enforcer) CreateTempToken(token string, service string, value string, timeout int64) (string, error) {
if token == "" {
return "", fmt.Errorf("token must not be empty")
}
err := e.setTempToken(service, token, value, timeout)
if err != nil {
return "", err
}
return token, nil
}
獲取剩餘時間
同樣是使用Adapter組件去獲取剩餘時間
func (e *Enforcer) GetTempTokenTimeout(service string, tempToken string) int64 {
if tempToken == "" {
return constant.NotValueExpire
}
return e.getTimeoutByTempToken(service, tempToken)
}
func (e *Enforcer) getTimeoutByTempToken(service string, token string) int64 {
return e.adapter.GetTimeout(e.spliceTempTokenKey(service, token))
}
解析臨時token
解析即是通過service,token去Adapter中獲取對應的信息。
func (e *Enforcer) ParseTempToken(service string, tempToken string) string {
if tempToken == "" {
return ""
}
return e.getByTempToken(service, tempToken)
}
刪除臨時token
刪除臨時token則是從Adapter組件中刪除對應的k,v數據
func (e *Enforcer) DeleteTempToken(service string, tempToken string) error {
return e.deleteByTempToken(service, tempToken)
}
測試
func TestEnforcer_TempToken(t *testing.T) {
enforcer, _ := NewTestEnforcer(t)
service := "code"
tempToken, err := enforcer.CreateTempToken("tempToken", service, "1234", -1)
if err != nil {
t.Fatalf("CreateTempToken() failed: %v", err)
}
if !reflect.DeepEqual(tempToken, "tempToken") {
t.Fatalf("token error, want is %v", "1234")
}
timeout := enforcer.GetTempTokenTimeout(service, tempToken)
if timeout != -1 {
t.Errorf("GetTempTokenTimeout() failed, unexpected timeout: %v", timeout)
}
codeValue := enforcer.ParseTempToken("code", tempToken)
if codeValue != "1234" {
t.Errorf("ParseTempToken() failed, unexpected codeValue: %v", codeValue)
}
// delete
if enforcer.DeleteTempToken(service, tempToken) != nil {
t.Fatalf("DeleteTempToken() failed: %v", err)
}
tokenTimeout := enforcer.GetTempTokenTimeout(service, tempToken)
if tokenTimeout != -2 {
t.Errorf("GetTempTokenTimeout() failed, unexpected tokenTimeout: %v", tokenTimeout)
}
codeValue = enforcer.ParseTempToken(service, tempToken)
if codeValue != "" {
t.Errorf("ParseTempToken() failed, unexpected codeValue: %v", codeValue)
}
// create token
tempToken, err = enforcer.CreateTempTokenByStyle("uuid", service, "1234", -1)
if err != nil {
t.Fatalf("CreateTempTokenByStyle() failed: %v", err)
}
// delete
if enforcer.DeleteTempToken(service, tempToken) != nil {
t.Fatalf("DeleteTempToken() failed: %v", err)
}
}
--- PASS: TestEnforcer_TempToken (0.01s)
PASS