提交 01d8a3d1 编写于 作者: Mr.奇淼('s avatar Mr.奇淼(

增加令牌自动续期功能

上级 a84767b4
......@@ -88,10 +88,12 @@ func tokenNext(c *gin.Context, user model.SysUser) {
UUID: user.UUID,
ID: user.ID,
NickName: user.NickName,
Username: user.Username,
AuthorityId: user.AuthorityId,
BufferTime: 60*60*24, // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
StandardClaims: jwt.StandardClaims{
NotBefore: time.Now().Unix() - 1000, // 签名生效时间
ExpiresAt: time.Now().Unix() + 60*60*24*7, // 过期时间 一周
ExpiresAt: time.Now().Unix() + 60*60*24*7, // 过期时间 7天
Issuer: "qmPlus", // 签名的发行者
},
}
......@@ -108,11 +110,9 @@ func tokenNext(c *gin.Context, user model.SysUser) {
}, c)
return
}
var loginJwt model.JwtBlacklist
loginJwt.Jwt = token
err, jwtStr := service.GetRedisJWT(user.Username)
if err == redis.Nil {
if err := service.SetRedisJWT(loginJwt, user.Username); err != nil {
if err := service.SetRedisJWT(token, user.Username); err != nil {
response.FailWithMessage("设置登录状态失败", c)
return
}
......@@ -130,7 +130,7 @@ func tokenNext(c *gin.Context, user model.SysUser) {
response.FailWithMessage("jwt作废失败", c)
return
}
if err := service.SetRedisJWT(loginJwt, user.Username); err != nil {
if err := service.SetRedisJWT(jwtStr, user.Username); err != nil {
response.FailWithMessage("设置登录状态失败", c)
return
}
......
......@@ -9,6 +9,7 @@ import (
"gin-vue-admin/service"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"strconv"
"time"
)
......@@ -16,9 +17,6 @@ func JWTAuth() gin.HandlerFunc {
return func(c *gin.Context) {
// 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localSstorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
token := c.Request.Header.Get("x-token")
modelToken := model.JwtBlacklist{
Jwt: token,
}
if token == "" {
response.Result(response.ERROR, gin.H{
"reload": true,
......@@ -26,7 +24,7 @@ func JWTAuth() gin.HandlerFunc {
c.Abort()
return
}
if service.IsBlacklist(token, modelToken) {
if service.IsBlacklist(token) {
response.Result(response.ERROR, gin.H{
"reload": true,
}, "您的帐户异地登陆或令牌失效", c)
......@@ -50,6 +48,24 @@ func JWTAuth() gin.HandlerFunc {
c.Abort()
return
}
if claims.ExpiresAt - time.Now().Unix()<claims.BufferTime {
claims.ExpiresAt = time.Now().Unix() + 60*60*24*7
newToken,_ := j.CreateToken(*claims)
newClaims,_ := j.ParseToken(newToken)
c.Header("new-token",newToken)
c.Header("new-expires-at",strconv.FormatInt(newClaims.ExpiresAt,10))
if global.GVA_CONFIG.System.UseMultipoint {
err,RedisJwtToken := service.GetRedisJWT(newClaims.Username)
if err!=nil {
global.GVA_LOG.Error(err)
}else{
service.JsonInBlacklist(model.JwtBlacklist{Jwt: RedisJwtToken})
//当之前的取成功时才进行拉黑操作
}
// 无论如何都要记录当前的活跃状态
_ = service.SetRedisJWT(newToken,newClaims.Username)
}
}
c.Set("claims", claims)
c.Next()
}
......@@ -111,20 +127,20 @@ func (j *JWT) ParseToken(tokenString string) (*request.CustomClaims, error) {
}
// 更新token
func (j *JWT) RefreshToken(tokenString string) (string, error) {
jwt.TimeFunc = func() time.Time {
return time.Unix(0, 0)
}
token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
return j.SigningKey, nil
})
if err != nil {
return "", err
}
if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid {
jwt.TimeFunc = time.Now
claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix()
return j.CreateToken(*claims)
}
return "", TokenInvalid
}
//func (j *JWT) RefreshToken(tokenString string) (string, error) {
// jwt.TimeFunc = func() time.Time {
// return time.Unix(0, 0)
// }
// token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
// return j.SigningKey, nil
// })
// if err != nil {
// return "", err
// }
// if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid {
// jwt.TimeFunc = time.Now
// claims.StandardClaims.ExpiresAt = time.Now().Unix() + 60*60*24*7
// return j.CreateToken(*claims)
// }
// return "", TokenInvalid
//}
......@@ -9,7 +9,9 @@ import (
type CustomClaims struct {
UUID uuid.UUID
ID uint
Username string
NickName string
AuthorityId string
BufferTime int64
jwt.StandardClaims
}
......@@ -3,6 +3,7 @@ package service
import (
"gin-vue-admin/global"
"gin-vue-admin/model"
"time"
)
// @title JsonInBlacklist
......@@ -23,8 +24,8 @@ func JsonInBlacklist(jwtList model.JwtBlacklist) (err error) {
// @param jwtList model.JwtBlacklist
// @return err error
func IsBlacklist(jwt string, jwtList model.JwtBlacklist) bool {
isNotFound := global.GVA_DB.Where("jwt = ?", jwt).First(&jwtList).RecordNotFound()
func IsBlacklist(jwt string) bool {
isNotFound := global.GVA_DB.Where("jwt = ?", jwt).First(&model.JwtBlacklist{}).RecordNotFound()
return !isNotFound
}
......@@ -47,7 +48,9 @@ func GetRedisJWT(userName string) (err error, redisJWT string) {
// @param userName string
// @return err error
func SetRedisJWT(jwtList model.JwtBlacklist, userName string) (err error) {
err = global.GVA_REDIS.Set(userName, jwtList.Jwt, 1000*1000*1000*60*60*24*7).Err()
func SetRedisJWT(jwt string, userName string) (err error) {
// 此处过期时间等于jwt过期时间
timer := 60*60*24*7*time.Second
err = global.GVA_REDIS.Set(userName, jwt, timer).Err()
return err
}
......@@ -7,14 +7,6 @@ const whiteList = ['login', 'register']
router.beforeEach(async(to, from, next) => {
const token = store.getters['user/token']
// if (token) {
// const expiresAt = store.getters['user/expiresAt']
// const nowUnix = new Date().getTime()
// const hasExpires = (expiresAt - nowUnix) < 0
// if (hasExpires) {
// store.dispatch['user/claerAll']
// }
// }
// 在白名单中的判断情况
if (whiteList.indexOf(to.name) > -1) {
if (token) {
......
......@@ -11,7 +11,6 @@ export const user = {
authority: "",
},
token: "",
expiresAt: ""
},
mutations: {
setUserInfo(state, userInfo) {
......@@ -22,14 +21,9 @@ export const user = {
// 这里的 `state` 对象是模块的局部状态
state.token = token
},
setExpiresAt(state, expiresAt) {
// 这里的 `state` 对象是模块的局部状态
state.expiresAt = expiresAt
},
LoginOut(state) {
state.userInfo = {}
state.token = ""
state.expiresAt = ""
router.push({ name: 'login', replace: true })
sessionStorage.clear()
window.location.reload()
......@@ -45,7 +39,6 @@ export const user = {
const res = await login(loginInfo)
commit('setUserInfo', res.data.user)
commit('setToken', res.data.token)
commit('setExpiresAt', res.data.expiresAt)
if (res.code == 0) {
const redirect = router.history.current.query.redirect
if (redirect) {
......@@ -69,8 +62,6 @@ export const user = {
token(state) {
return state.token
},
expiresAt(state) {
return state.expiresAt
}
}
}
\ No newline at end of file
......@@ -21,13 +21,13 @@ const showLoading = () => {
}
const closeLoading = () => {
acitveAxios--
if (acitveAxios <= 0) {
clearTimeout(timer)
loadingInstance && loadingInstance.close()
acitveAxios--
if (acitveAxios <= 0) {
clearTimeout(timer)
loadingInstance && loadingInstance.close()
}
}
}
//http request 拦截器
//http request 拦截器
service.interceptors.request.use(
config => {
showLoading()
......@@ -37,7 +37,7 @@ service.interceptors.request.use(
config.headers = {
'Content-Type': 'application/json',
'x-token': token,
'x-user-id':user.ID
'x-user-id': user.ID
}
return config;
},
......@@ -57,6 +57,9 @@ service.interceptors.request.use(
service.interceptors.response.use(
response => {
closeLoading()
if (response.headers["new-token"]) {
store.commit('user/setToken', response.headers["new-token"])
}
if (response.data.code == 0 || response.headers.success === "true") {
return response.data
} else {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册