认证
应用中“认证”的工作流:
- 通过发送http请求到资源“/users/register”以使用户注册进系统
- 通过发送http请求到资源“/users/login”以使已注册用户登录到系统。服务器证实登录证书并产生一个JWT作为访问令牌。此令牌可以访问受保护的RESTful API服务器的资源。
- 用户可以使用JWT访问受保护的RESTful API服务器的资源。在"授权"的HTTP头部中,用户必须发送这个JWT作为“bearer token”。
产生和核实JWT
产生JWT
补充JWT知识;了解jwt-go的用法。
生成JWT的函数:
src/taskmanager2/common2/auth.go
// GenerateJWT generates a new JWT token
func GenerateJWT(name, role string) (string, error) {
// Create the Claims
claims := AppClaims{
name,
role,
jwt.StandardClaims{
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
Issuer: "admin",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
ss, err := token.SignedString(signKey)
if err != nil {
return "", err
}
return ss, nil
}
发送JWT给服务器
在postman中,使用如下格式:
"Authorization": "Bearer token_string”,
例如:
"Authorization":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"
可以把JWT发送给服务器。
授权JWT
用于验证JWT的中间件
// Authorize Middleware for validating JWT tokens
func Authorize() gin.HandlerFunc {
return func(c *gin.Context) {
// Get token from request
token, err := request.ParseFromRequestWithClaims(c.Request, request.OAuth2Extractor, &AppClaims{}, func(token *jwt.Token) (interface{}, error) {
return verifyKey, nil
})
if err != nil {
switch err.(type) {
case *jwt.ValidationError: // JWT validation error
vErr := err.(*jwt.ValidationError)
switch vErr.Errors {
case jwt.ValidationErrorExpired: //JWT expired
DisplayAppError(
c,
err,
"Access Token is expired, get a new Token",
401,
)
default:
DisplayAppError(
c,
err,
"Error while parsing the Access Token!",
500,
)
}
default:
DisplayAppError(
c,
err,
"Error while parsing Access Token!",
500)
}
c.Abort()
}
if token.Valid {
c.Set("user", token.Claims.(*AppClaims).UserName)
c.Next()
} else {
DisplayAppError(
c,
err,
"Invalid Access Token",
401,
)
c.Abort()
}
}
}
以资源“task”为例,在路径中使用router.Use()来添加授权中间件。
src/taskmanager2/routers2/task.go
package routers2
import (
"gopkg.in/gin-gonic/gin.v1"
"taskmanager2/controllers2"
"taskmanager2/common2"
)
// SetTaskRoutes configures routes for task entity
func SetTaskRoutes(router *gin.Engine) *gin.Engine {
taR := router.Group("/tm2/tasks")
taR.Use(common2.Authorize())
{
taR.POST("", controllers2.CreateTask)
taR.PUT(":id", controllers2.UpdateTask)
taR.DELETE(":id", controllers2.DeleteTask)
taR.GET("", controllers2.GetTasks)
taR.GET("t/:id/", controllers2.GetTaskByID)
taR.GET("users/:email/", controllers2.GetTasksByUser)
}
return router
}