文章目錄
- 1. 相關函數
- 2. router對其調用
- 3. 其他接口身份驗證
- 4. postman 測試
-
- 4.1 測試登入接口
- 4.2 postman設定Cookies
- 4.3 其他接口調用身份驗證測試
1. 相關函數
建立如下函數:
- 登入函數:登入接口調用該函數
- 身份驗證:其他函數調用該函數,用token判斷身份是否合法
- 重新整理token:登入接口調用該函數,如果token驗證通過則發放新token
- 驗證token:需要驗證身份的服務調用該函數判斷token是否合法
- 生成token: 其他函數調用該函數,用以生成新token
package router
import (
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"time"
)
type LoginInfo struct {
UserName string `json:"user_name"`
Password string `json:"password"`
}
type JWTClaims struct { // token裡面添加使用者資訊,驗證token後可能會用到使用者資訊
jwt.StandardClaims
UserID int `json:"user_id"`
Password string `json:"password"`
Username string `json:"username"`
FullName string `json:"full_name"`
Permissions []string `json:"permissions"`
}
var (
Secret = "LiuBei" // 加鹽
ExpireTime = 3600*24 // token有效期
)
//登入
func Login(c *gin.Context) {
var loginRequest LoginInfo
err := c.Bind(&loginRequest)
if err != nil {
c.JSON(400,err.Error())
return
}
//模拟使用者認證
if loginRequest.UserName != "liuBei" || loginRequest.Password != "[email protected]" {
c.JSON(401,gin.H{"err":"賬号或密碼錯誤"})
return
}
claims := &JWTClaims{
UserID: 1,
Username: loginRequest.UserName,
Password: loginRequest.Password,
FullName: loginRequest.UserName,
Permissions: []string{},
}
claims.IssuedAt = time.Now().Unix()
claims.ExpiresAt = time.Now().Add(time.Second * time.Duration(ExpireTime)).Unix()
signedToken,err:=getToken(claims)
if err!=nil {
c.JSON(400,err.Error())
return
}
//fmt.Printf(signedToken)
c.JSON(200, gin.H{"token": signedToken})
}
//身份驗證
func Verify(c *gin.Context)(result bool,userName string,err error) {
strToken,err := c.Cookie("Crow")
if strToken == ""{
result = false
return result,"",nil
}
claim,err := verifyAction(strToken)
if err != nil {
result = false
return result,"",nil
}
result = true
userName = claim.Username
return result,userName,nil
}
//重新整理token
func Refresh(c *gin.Context) {
strToken,err := c.Cookie("Crow")
claims,err := verifyAction(strToken)
if err != nil {
c.JSON(400,gin.H{"err":err.Error()})
return
}
claims.ExpiresAt = time.Now().Unix() + (claims.ExpiresAt - claims.IssuedAt)
signedToken,err:=getToken(claims)
if err!=nil{
c.JSON(400,gin.H{"err":err.Error()})
return
}
c.JSON(200,gin.H{"data": signedToken })
}
//驗證token是否存在,存在則擷取資訊
func verifyAction(strToken string) (claims *JWTClaims,err error) {
token, err := jwt.ParseWithClaims(strToken, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(Secret), nil
})
if err != nil {
return nil, err
}
claims, ok := token.Claims.(*JWTClaims)
if !ok {
return nil, err
}
if err := token.Claims.Valid(); err != nil {
return nil, err
}
return claims, nil
}
//生成token
func getToken(claims *JWTClaims)(signedToken string,err error){
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
signedToken, err = token.SignedString([]byte(Secret))
if err != nil {
return "",err
}
return signedToken,nil
}
2. router對其調用
loginGroup := r.Group("/api/v1/login")
{
loginGroup.POST("/", Login) //登入伺服器
loginGroup.POST("/refresh", Refresh) //生成新token
}
3. 其他接口身份驗證
以上一章k8s服務的 查詢deployment接口為例,開頭添加如下内容:
func GetDeployment(c *gin.Context) {
//身份認證
checkUser,_,err := Verify(c) //第二個值是使用者名,這裡沒有使用
if err != nil{
c.JSON(400,gin.H{"err":err.Error()})
return
}
if checkUser == false {
c.JSON(400,gin.H{"err":"身份認證失敗"})
return
}
//查詢開始
……
}
4. postman 測試
4.1 測試登入接口
登入成功擷取到token。
4.2 postman設定Cookies
注意: Crow
這個 key的名字是剛才我們在代碼裡邊指定的
4.3 其他接口調用身份驗證測試
- 成功的情況
我們可以看到Headers裡多了我們剛才添加的Cookie,是我們剛才添加的Crow
- 驗證失敗的情況
我們把剛才的Cookie改成錯的,然後再測試: