1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package middleware
 
import (
    "aps_crm/conf"
    "aps_crm/model"
    "aps_crm/pkg/contextx"
    "aps_crm/pkg/ecode"
    "aps_crm/pkg/logx"
    "aps_crm/service"
    "aps_crm/utils"
    "github.com/gin-gonic/gin"
    "strconv"
    "strings"
    "time"
)
 
var jwtService = service.ServiceGroup.JwtService
 
func JWTAuth() gin.HandlerFunc {
    return func(c *gin.Context) {
        ctx := new(contextx.Context).SetCtx(c)
        // 我们这里jwt鉴权取头部信息 Authorization 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localStorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
        token := c.Request.Header.Get("Authorization")
        if token == "" {
            ctx.Fail(ecode.JWTEmpty)
            c.Abort()
            return
        }
        slices := strings.Split(token, " ")
        if len(slices) == 2 {
            token = slices[1]
        }
        if jwtService.IsBlacklist(token) {
            ctx.Fail(ecode.JWTInBlackList)
            c.Abort()
            return
        }
        j := utils.NewJWT()
        // parseToken 解析token包含的信息
        claims, err := j.ParseToken(token)
        if err != nil {
            if err == utils.TokenExpired {
                ctx.Fail(ecode.JWTExpire)
                c.Abort()
                return
            }
            ctx.Fail(ecode.JWTParseErr)
            c.Abort()
            return
        }
 
        // 已登录用户被管理员禁用 需要使该用户的jwt失效 此处比较消耗性能 如果需要 请自行打开
        // 用户被删除的逻辑 需要优化 此处比较消耗性能 如果需要 请自行打开
 
        //if user, err := userService.FindUserByUuid(claims.UUID.String()); err != nil || user.Hidden == 2 {
        //    _ = jwtService.JsonInBlacklist(system.JwtBlacklist{Jwt: token})
        //    response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c)
        //    c.Abort()
        //}
        if claims.ExpiresAt-time.Now().Unix() < claims.BufferTime {
            dr, _ := utils.ParseDuration(conf.Conf.JWT.ExpiresTime)
            claims.ExpiresAt = time.Now().Add(dr).Unix()
            newToken, _ := j.CreateTokenByOldToken(token, *claims)
            newClaims, _ := j.ParseToken(newToken)
            c.Header("new-token", newToken)
            c.Header("new-expires-at", strconv.FormatInt(newClaims.ExpiresAt, 10))
            if conf.Conf.System.UseMultipoint {
                RedisJwtToken, err := jwtService.GetRedisJWT(newClaims.Username)
                if err != nil {
                    logx.Errorf("get redis jwt failed err:%v", err)
                } else { // 当之前的取成功时才进行拉黑操作
                    _ = jwtService.JsonInBlacklist(model.JwtBlacklist{Jwt: RedisJwtToken})
                }
                // 无论如何都要记录当前的活跃状态
                _ = jwtService.SetRedisJWT(newToken, newClaims.Username)
            }
        }
        c.Set("claims", claims)
        c.Next()
    }
}
 
func JWTAuth2() gin.HandlerFunc {
    return func(c *gin.Context) {
        ctx := new(contextx.Context).SetCtx(c)
        // 我们这里jwt鉴权取头部信息 Authorization 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localStorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
        token := c.Request.Header.Get("Authorization")
        if token == "" {
            ctx.Fail(ecode.JWTEmpty)
            c.Abort()
            return
        }
        slices := strings.Split(token, " ")
        if len(slices) == 2 {
            token = slices[1]
        }
        j := utils.NewJWT()
        // parseToken 解析token包含的信息
        claims, err := j.ParseToken(token)
        if err != nil {
            if err == utils.TokenExpired {
                c.Next()
                return
            }
            c.Next()
            return
        }
        userInfo := service.GetUserBaseCache(claims.UserId)
        if userInfo == nil {
            SyncUserInfo([]string{claims.UserId})
            userInfo = service.GetUserBaseCache(claims.UserId)
        }
 
        SetActiveTime(claims.UserId)
 
        claims.CrmUserId = userInfo.UserId
        claims.NickName = userInfo.NickName
        c.Set("claims", claims)
        if CheckAuth(c.Request.URL.Path, token) {
            c.Next()
        } else {
            ctx.Fail(ecode.JWTDisabled)
            c.Abort()
            return
        }
    }
}