Browse Source

增加了多点登录限制 体验需要再 static\config中 把 system中的useMultipoint 修改为 true

pixel 5 years ago
parent
commit
6e424b6b89

+ 18 - 0
QMPlusServer/config/config.go

@@ -10,7 +10,20 @@ type Config struct {
 	MysqlAdmin   MysqlAdmin
 	Qiniu        Qiniu
 	CasbinConfig CasbinConfig
+	RedisAdmin   RedisAdmin
+	System       System
+	JWT          JWT
 }
+
+type System struct {
+	UseMultipoint bool
+	Env           string
+}
+
+type JWT struct {
+	SigningKey string
+}
+
 type CasbinConfig struct {
 	ModelPath string // casbin model地址配置
 }
@@ -23,6 +36,11 @@ type MysqlAdmin struct { // mysql admin 数据库配置
 	Config   string
 }
 
+type RedisAdmin struct { // Redis admin 数据库配置
+	Addr     string
+	Password string
+	DB       int
+}
 type Qiniu struct { // 七牛 密钥配置
 	AccessKey string
 	SecretKey string

+ 34 - 2
QMPlusServer/controller/api/sys_user.go

@@ -2,12 +2,14 @@ package api
 
 import (
 	"fmt"
+	"gin-vue-admin/config"
 	"gin-vue-admin/controller/servers"
 	"gin-vue-admin/middleware"
 	"gin-vue-admin/model/modelInterface"
 	"gin-vue-admin/model/sysModel"
 	"github.com/dgrijalva/jwt-go"
 	"github.com/gin-gonic/gin"
+	"github.com/go-redis/redis"
 	uuid "github.com/satori/go.uuid"
 	"mime/multipart"
 	"time"
@@ -73,7 +75,7 @@ func Login(c *gin.Context) {
 //登录以后签发jwt
 func tokenNext(c *gin.Context, user sysModel.SysUser) {
 	j := &middleware.JWT{
-		[]byte("qmPlus"), // 唯一签名
+		[]byte(config.GinVueAdminconfig.JWT.SigningKey), // 唯一签名
 	}
 	clams := middleware.CustomClaims{
 		UUID:        user.UUID,
@@ -90,7 +92,37 @@ func tokenNext(c *gin.Context, user sysModel.SysUser) {
 	if err != nil {
 		servers.ReportFormat(c, false, "获取token失败", gin.H{})
 	} else {
-		servers.ReportFormat(c, true, "登录成功", gin.H{"user": user, "token": token, "expiresAt": clams.StandardClaims.ExpiresAt * 1000})
+		if config.GinVueAdminconfig.System.UseMultipoint {
+			var loginJwt sysModel.JwtBlacklist
+			loginJwt.Jwt = token
+			err, jwtStr := loginJwt.GetRedisJWT(user.Username)
+			if err == redis.Nil {
+				err2 := loginJwt.SetRedisJWT(user.Username)
+				if err2 != nil {
+					servers.ReportFormat(c, false, "设置登录状态失败", gin.H{})
+				} else {
+					servers.ReportFormat(c, true, "登录成功", gin.H{"user": user, "token": token, "expiresAt": clams.StandardClaims.ExpiresAt * 1000})
+				}
+			} else if err != nil {
+				servers.ReportFormat(c, false, fmt.Sprintf("%v", err), gin.H{})
+			} else {
+				var blackjWT sysModel.JwtBlacklist
+				blackjWT.Jwt = jwtStr
+				err3 := blackjWT.JsonInBlacklist()
+				if err3 != nil {
+					servers.ReportFormat(c, false, "jwt作废失败", gin.H{})
+				} else {
+					err2 := loginJwt.SetRedisJWT(user.Username)
+					if err2 != nil {
+						servers.ReportFormat(c, false, "设置登录状态失败", gin.H{})
+					} else {
+						servers.ReportFormat(c, true, "登录成功", gin.H{"user": user, "token": token, "expiresAt": clams.StandardClaims.ExpiresAt * 1000})
+					}
+				}
+			}
+		} else {
+			servers.ReportFormat(c, true, "登录成功", gin.H{"user": user, "token": token, "expiresAt": clams.StandardClaims.ExpiresAt * 1000})
+		}
 	}
 }
 

+ 1 - 0
QMPlusServer/go.mod

@@ -10,6 +10,7 @@ require (
 	github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
 	github.com/fsnotify/fsnotify v1.4.7
 	github.com/gin-gonic/gin v1.4.0
+	github.com/go-redis/redis v6.15.6+incompatible
 	github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
 	github.com/jinzhu/gorm v1.9.10
 	github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 // indirect

+ 25 - 0
QMPlusServer/init/initRedis/init_redis.go

@@ -0,0 +1,25 @@
+package initRedis
+
+import (
+	"fmt"
+	"gin-vue-admin/config"
+	"github.com/go-redis/redis"
+)
+
+var DEFAULTREDIS *redis.Client
+
+func InitRedis() (client *redis.Client) {
+	client = redis.NewClient(&redis.Options{
+		Addr:     config.GinVueAdminconfig.RedisAdmin.Addr,
+		Password: config.GinVueAdminconfig.RedisAdmin.Password, // no password set
+		DB:       config.GinVueAdminconfig.RedisAdmin.DB,       // use default DB
+	})
+	pong, err := client.Ping().Result()
+	if err != nil {
+		fmt.Println(pong, err)
+	} else {
+		fmt.Println(pong, err)
+		DEFAULTREDIS = client
+	}
+	return client
+}

+ 8 - 4
QMPlusServer/main.go

@@ -3,6 +3,7 @@ package main
 import (
 	"fmt"
 	"gin-vue-admin/config"
+	"gin-vue-admin/init/initRedis"
 	"gin-vue-admin/init/initRouter"
 	"gin-vue-admin/init/qmlog"
 	"gin-vue-admin/init/qmsql"
@@ -22,10 +23,13 @@ import (
 func main() {
 	qmlog.InitLog()                                            // 初始化日志
 	db := qmsql.InitMysql(config.GinVueAdminconfig.MysqlAdmin) // 链接初始化数据库
-	registTable.RegistTable(db)                                //注册数据库表
-	defer qmsql.DEFAULTDB.Close()                              // 程序结束前关闭数据库链接
-	Router := initRouter.InitRouter()                          //注册路由
-	qmlog.QMLog.Info("服务器开启")                                  // 日志测试代码
+	if config.GinVueAdminconfig.System.UseMultipoint {
+		_ = initRedis.InitRedis() // 初始化redis服务
+	}
+	registTable.RegistTable(db)       //注册数据库表
+	defer qmsql.DEFAULTDB.Close()     // 程序结束前关闭数据库链接
+	Router := initRouter.InitRouter() //注册路由
+	qmlog.QMLog.Info("服务器开启")         // 日志测试代码
 	//Router.RunTLS(":443","ssl.pem", "ssl.key")  // https支持 需要添加中间件
 	s := &http.Server{
 		Addr:           ":8888",

+ 8 - 20
QMPlusServer/middleware/jwt.go

@@ -2,6 +2,7 @@ package middleware
 
 import (
 	"errors"
+	"gin-vue-admin/config"
 	"gin-vue-admin/controller/servers"
 	"gin-vue-admin/model/sysModel"
 	"github.com/dgrijalva/jwt-go"
@@ -15,7 +16,7 @@ func JWTAuth() gin.HandlerFunc {
 		// 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localSstorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
 		token := c.Request.Header.Get("x-token")
 		ModelToken := sysModel.JwtBlacklist{
-			Jwt:token,
+			Jwt: token,
 		}
 		if token == "" {
 			servers.ReportFormat(c, false, "未登录或非法访问", gin.H{
@@ -24,7 +25,7 @@ func JWTAuth() gin.HandlerFunc {
 			c.Abort()
 			return
 		}
-		if ModelToken.IsBlacklist(token){
+		if ModelToken.IsBlacklist(token) {
 			servers.ReportFormat(c, false, "授权已失效", gin.H{
 				"reload": true,
 			})
@@ -58,11 +59,10 @@ type JWT struct {
 }
 
 var (
-	TokenExpired     error  = errors.New("Token is expired")
-	TokenNotValidYet error  = errors.New("Token not active yet")
-	TokenMalformed   error  = errors.New("That's not even a token")
-	TokenInvalid     error  = errors.New("Couldn't handle this token:")
-	SignKey          string = "qmPlus"
+	TokenExpired     error = errors.New("Token is expired")
+	TokenNotValidYet error = errors.New("Token not active yet")
+	TokenMalformed   error = errors.New("That's not even a token")
+	TokenInvalid     error = errors.New("Couldn't handle this token:")
 )
 
 type CustomClaims struct {
@@ -75,21 +75,10 @@ type CustomClaims struct {
 
 func NewJWT() *JWT {
 	return &JWT{
-		[]byte(GetSignKey()),
+		[]byte(config.GinVueAdminconfig.JWT.SigningKey),
 	}
 }
 
-//获取token
-func GetSignKey() string {
-	return SignKey
-}
-
-// 这是SignKey
-func SetSignKey(key string) string {
-	SignKey = key
-	return SignKey
-}
-
 //创建一个token
 func (j *JWT) CreateToken(claims CustomClaims) (string, error) {
 	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
@@ -146,4 +135,3 @@ func (j *JWT) RefreshToken(tokenString string) (string, error) {
 	}
 	return "", TokenInvalid
 }
-

+ 17 - 5
QMPlusServer/model/sysModel/sys_jwt_blacklist.go

@@ -1,6 +1,7 @@
 package sysModel
 
 import (
+	"gin-vue-admin/init/initRedis"
 	"gin-vue-admin/init/qmsql"
 	"github.com/jinzhu/gorm"
 )
@@ -10,14 +11,25 @@ type JwtBlacklist struct {
 	Jwt string `gorm:"type:text"`
 }
 
-func(j *JwtBlacklist)JsonInBlacklist()(err error){
+func (j *JwtBlacklist) JsonInBlacklist() (err error) {
 	err = qmsql.DEFAULTDB.Create(j).Error
 	return
 }
 
-
 //判断JWT是否在黑名单内部
-func (j *JwtBlacklist)IsBlacklist(Jwt string)(bool){
-	isNotFound := qmsql.DEFAULTDB.Where("jwt = ?",Jwt).First(j).RecordNotFound()
+func (j *JwtBlacklist) IsBlacklist(Jwt string) bool {
+	isNotFound := qmsql.DEFAULTDB.Where("jwt = ?", Jwt).First(j).RecordNotFound()
 	return !isNotFound
-}
+}
+
+//判断当前用户是否在线
+func (j *JwtBlacklist) GetRedisJWT(userName string) (err error, RedisJWT string) {
+	RedisJWT, err = initRedis.DEFAULTREDIS.Get(userName).Result()
+	return err, RedisJWT
+}
+
+//设置当前用户在线
+func (j *JwtBlacklist) SetRedisJWT(userName string) (err error) {
+	err = initRedis.DEFAULTREDIS.Set(userName, j.Jwt, 1000*1000*1000*60*60*24*7).Err()
+	return err
+}

+ 12 - 0
QMPlusServer/static/config/config.json

@@ -1,4 +1,11 @@
 {
+  "system": {
+    "useMultipoint": false,
+    "env": "develop"
+  },
+  "jwt": {
+    "signingKey":"qmPlus"
+  },
   "mysqlAdmin": {
     "username": "root",
     "password": "Aa@6447985",
@@ -6,6 +13,11 @@
     "dbname": "qmplus",
     "config": "charset=utf8&parseTime=True&loc=Local"
   },
+  "redisAdmin": {
+    "addr":     "127.0.0.1:6379",
+    "password": "",
+    "DB":0
+  },
   "qiniu": {
     "accessKey":"25j8dYBZ2wuiy0yhwShytjZDTX662b8xiFguwxzZ",
     "secretKey": "pgdbqEsf7ooZh7W3xokP833h3dZ_VecFXPDeG5JY"