1.导入依赖库
go get -u github.com/dgrijalva/jwt-go
2.生成token
import (
"fmt"
"github.com/gin-gonic/gin"
jwt "github.com/dgrijalva/jwt-go"
"net/http"
"time"
)
var jwtSecret=[]byte("secret")
type Claims struct {
Username string `json:"username"`
Password string `json:"password"`
jwt.StandardClaims
}
//生成token
func createToken(username,password string)(string,error) {
nowtime := time.Now()
expireTime := nowtime.Add(3*time.Hour)
claims := Claims{
username,
password,
jwt.StandardClaims{
ExpiresAt: expireTime.Unix(),
Issuer: "gin-blog",
},
}
//
tokenClaims:=jwt.NewWithClaims(jwt.SigningMethodHS256,claims)
token,err:=tokenClaims.SignedString(jwtSecret)
return token,err
}
3.解析token
//解析token
// 验证token的函数
func ParseToken(token string)(*Claims,error){
tokenClaims,err:=jwt.ParseWithClaims(token,&Claims{},func(token *jwt.Token)(interface{},error){
return jwtSecret,nil
})
if tokenClaims!=nil{
if claims,ok:=tokenClaims.Claims.(*Claims);ok && tokenClaims.Valid{
return claims,nil
}
}
//
return nil,err
}
4.在gin的应用
登录,获取token
func authHandler(c *gin.Context) {
// 用户发送用户名和密码过来
var user Claims
err := c.ShouldBind(&user)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": 2001,
"msg": "无效的参数",
})
return
}
fmt.Println(&user)
// 校验用户名和密码是否正确
if user.Username == "admin" && user.Password == "123456" {
// 生成Token
tokenString, _ := createToken(user.Username,user.Password)
c.JSON(http.StatusOK, gin.H{
"code": 2000,
"msg": "success",
"data": gin.H{"token": tokenString},
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 2002,
"msg": "鉴权失败",
})
return
}
r.POST("/auth", authHandler)
在其他接口加上解析token验证
// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
return func(c *gin.Context) {
// 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
// 这里假设Token放在Header的Authorization中,并使用Bearer开头
// 这里的具体实现方式要依据你的实际业务情况决定
authHeader := c.Request.Header.Get("token")
if authHeader == "" {
c.JSON(http.StatusOK, gin.H{
"code": 2003,
"msg": "请求头中auth为空",
})
c.Abort()
return
}
// 按空格分割
//parts := strings.SplitN(authHeader, " ", 2)
//if !(len(parts) == 2 && parts[0] == "Bearer") {
// c.JSON(http.StatusOK, gin.H{
// "code": 2004,
// "msg": "请求头中auth格式有误",
// })
// c.Abort()
// return
//}
// parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
mc, err := ParseToken(authHeader)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": 2005,
"msg": "无效的Token",
})
c.Abort()
return
}
// 将当前请求的username信息保存到请求的上下文c上
c.Set("username", mc.Username)
c.Next() // 后续的处理函数可以用过c.Get("username")来获取当前请求的用户信息
}
}
r.POST("/auth1",JWTAuthMiddleware(), func(c *gin.Context) {
username := c.MustGet("username").(string)
c.JSON(http.StatusOK, gin.H{
"code": 2000,
"msg": "success",
"data": gin.H{"username": username},
})
})
完整代码
package main
import (
"fmt"
"github.com/gin-gonic/gin"
jwt "github.com/dgrijalva/jwt-go"
"net/http"
"time"
)
var jwtSecret=[]byte("secret")
type Claims struct {
Username string `json:"username"`
Password string `json:"password"`
jwt.StandardClaims
}
//生成token
func createToken(username,password string)(string,error) {
nowtime := time.Now()
expireTime := nowtime.Add(3*time.Hour)
claims := Claims{
username,
password,
jwt.StandardClaims{
ExpiresAt: expireTime.Unix(),
Issuer: "gin-blog",
},
}
//
tokenClaims:=jwt.NewWithClaims(jwt.SigningMethodHS256,claims)
token,err:=tokenClaims.SignedString(jwtSecret)
return token,err
}
//解析token
// 验证token的函数
func ParseToken(token string)(*Claims,error){
tokenClaims,err:=jwt.ParseWithClaims(token,&Claims{},func(token *jwt.Token)(interface{},error){
return jwtSecret,nil
})
if tokenClaims!=nil{
if claims,ok:=tokenClaims.Claims.(*Claims);ok && tokenClaims.Valid{
return claims,nil
}
}
//
return nil,err
}
func authHandler(c *gin.Context) {
// 用户发送用户名和密码过来
var user Claims
err := c.ShouldBind(&user)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": 2001,
"msg": "无效的参数",
})
return
}
fmt.Println(&user)
// 校验用户名和密码是否正确
if user.Username == "admin" && user.Password == "123456" {
// 生成Token
tokenString, _ := createToken(user.Username,user.Password)
c.JSON(http.StatusOK, gin.H{
"code": 2000,
"msg": "success",
"data": gin.H{"token": tokenString},
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 2002,
"msg": "鉴权失败",
})
return
}
// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
return func(c *gin.Context) {
// 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
// 这里假设Token放在Header的Authorization中,并使用Bearer开头
// 这里的具体实现方式要依据你的实际业务情况决定
authHeader := c.Request.Header.Get("token")
if authHeader == "" {
c.JSON(http.StatusOK, gin.H{
"code": 2003,
"msg": "请求头中auth为空",
})
c.Abort()
return
}
// 按空格分割
//parts := strings.SplitN(authHeader, " ", 2)
//if !(len(parts) == 2 && parts[0] == "Bearer") {
// c.JSON(http.StatusOK, gin.H{
// "code": 2004,
// "msg": "请求头中auth格式有误",
// })
// c.Abort()
// return
//}
// parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
mc, err := ParseToken(authHeader)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": 2005,
"msg": "无效的Token",
})
c.Abort()
return
}
// 将当前请求的username信息保存到请求的上下文c上
c.Set("username", mc.Username)
c.Next() // 后续的处理函数可以用过c.Get("username")来获取当前请求的用户信息
}
}
func main() {
r := gin.Default()
r.POST("/auth", authHandler)
r.POST("/auth1",JWTAuthMiddleware(), func(c *gin.Context) {
username := c.MustGet("username").(string)
c.JSON(http.StatusOK, gin.H{
"code": 2000,
"msg": "success",
"data": gin.H{"username": username},
})
})
r.Run(":9090")
}