go get github.com/dgrijalva/jwt-go
// 定义一个密钥var jwtKey = []byte("define_a_secret")
// 定义Claimstype Claims struct {UserId uintjwt.StandardClaims}
type User struct {ID uint `form:"id"`Username string `form:"username"`Password string `form:"password"`}
// 产生JWTfunc GenerateToken(id uint) (tokenString string) {// user := User{ID: id, UserName: "张三"}expireTime := time.Now().Add(7 * 24 * time.Hour).Unix()issueTime := time.Now().Unix()claims := &Claims{// UserId: user.ID,UserId: id,StandardClaims: jwt.StandardClaims{// token过期时间ExpiresAt: expireTime,// 发放时间IssuedAt: issueTime,// 发放人Issuer: "Issuer",// 签名主题Subject: "user token",},}// 使用指定的签名方法创建签名对象token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)//使用指定的secret签名并获得完整的编码后的字符串tokentokenString, err := token.SignedString(jwtKey)if err != nil {fmt.Println(err)return}// fmt.Println(tokenString)return tokenString}
// 解析JWTfunc ParseToken(tokenString string) (*jwt.Token, *Claims, error) {claims := &Claims{}token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (i interface{}, err error) {return jwtKey, nil})return token, claims, err}
package mainimport ("github.com/gin-gonic/gin")func main() {r := gin.Default()// 登录,验证username,password,产生tokenr.POST("/login", loginHandle)r.Run(":8080")}
// loginHandlefunc loginHandle(c *gin.Context) {// form表单提交username和passwordusername := c.PostForm("username")password := c.PostForm("password")// 认证成功if username == "zhangsan" && password == "123456" {// tokentokenString := GenerateToken(222)c.JSON(200, gin.H{"code": http.StatusOK,"msg": "OK","token": tokenString,})} else {c.JSON(http.StatusOK, gin.H{"code": http.StatusUnauthorized,"msg": "Unauthorized","token": nil,})}}
// 访问用户资源(要求必须认证的用户才能访问)r.GET("/users", usersHandle)
// usersHandlefunc usersHandle(c *gin.Context) {// userId, ok := c.Get("userId")// if !ok {// return// }// c.String(http.StatusOK, userId)// 查询用户数据,返回c.String(http.StatusOK, "users")}
■ ■■■■
// 认证中间件func AuthMiddleWare() gin.HandlerFunc {return func (ctx *gin.Context) {// 假设Token放在Header的Authorization中,并使用Bearer开头tokenString := ctx.GetHeader("Authorization")if tokenString == "" || !strings.HasPrefix(tokenString, "Bearer ") {ctx.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized,"msg": "权限不足",})ctx.Abort()return}// 去掉BearertokenString = tokenString[7:]// 使用之前定义好的解析JWT的函数 ParseToken 来解析它token, claims, err := ParseToken(tokenString)if err != nil || !token.Valid {ctx.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized,"msg": "权限不足",})ctx.Abort()return}// 验证通过,获取claim中的useriduserId := claims.UserIdctx.Set("userId", userId)ctx.Next()}}
// 访问用户资源(要求必须认证的用户才能访问)r.GET("/users", AuthMiddleWare(), usersHandle)
至此,所有的逻辑都已完成。
■ ■■■■
package mainimport ("fmt""net/http""strings""time""github.com/dgrijalva/jwt-go""github.com/gin-gonic/gin")// 定义Claimstype Claims struct {UserId uintjwt.StandardClaims}type User struct {ID uint `form:"id"`Username string `form:"username"`Password string `form:"password"`}// 定义一个密钥var jwtKey = []byte("define_a_secret")func main() {r := gin.Default()// 登录,验证username,password,产生tokenr.POST("/login", loginHandle)// 访问用户资源(要求必须认证的用户才能访问)r.GET("/users", AuthMiddleWare(), usersHandle)r.Run(":8080")}// usersHandlefunc usersHandle(c *gin.Context) {// userId, ok := c.Get("userId")// if !ok {// return// }// c.String(http.StatusOK, userId)// 查询用户数据,返回c.String(http.StatusOK, "users")}// loginHandlefunc loginHandle(c *gin.Context) {// form表单提交username和passwordusername := c.PostForm("username")password := c.PostForm("password")// 认证成功if username == "zhangsan" && password == "123456" {// tokentokenString := GenerateToken(222)c.JSON(200, gin.H{"code": http.StatusOK,"msg": "OK","token": tokenString,})} else {c.JSON(http.StatusOK, gin.H{"code": http.StatusUnauthorized,"msg": "Unauthorized","token": nil,})}}// 产生JWTfunc GenerateToken(id uint) (tokenString string) {// user := User{ID: id, UserName: "张三"}expireTime := time.Now().Add(7 * 24 * time.Hour).Unix()issueTime := time.Now().Unix()claims := &Claims{// UserId: user.ID,UserId: id,StandardClaims: jwt.StandardClaims{// token过期时间ExpiresAt: expireTime,// 发放时间IssuedAt: issueTime,// 发放人Issuer: "Issuer",// 签名主题Subject: "user token",},}// 使用指定的签名方法创建签名对象token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)//使用指定的secret签名并获得完整的编码后的字符串tokentokenString, err := token.SignedString(jwtKey)if err != nil {fmt.Println(err)return}// fmt.Println(tokenString)return tokenString}// 解析JWTfunc ParseToken(tokenString string) (*jwt.Token, *Claims, error) {claims := &Claims{}token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (i interface{}, err error) {return jwtKey, nil})return token, claims, err}// 认证中间件func AuthMiddleWare() gin.HandlerFunc {return func (ctx *gin.Context) {// 假设Token放在Header的Authorization中,并使用Bearer开头tokenString := ctx.GetHeader("Authorization")if tokenString == "" || !strings.HasPrefix(tokenString, "Bearer ") {ctx.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized,"msg": "权限不足",})ctx.Abort()return}// 去掉BearertokenString = tokenString[7:]// 使用之前定义好的解析JWT的函数 ParseToken 来解析它token, claims, err := ParseToken(tokenString)if err != nil || !token.Valid {ctx.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized,"msg": "权限不足",})ctx.Abort()return}// 验证通过,获取claim中的useriduserId := claims.UserIdctx.Set("userId", userId)ctx.Next()}}