jflyfox 4 жил өмнө
parent
commit
02ccd0e949

+ 120 - 13
README.md

@@ -1,6 +1,6 @@
 # gtoken
 
-#### 介绍
+## 介绍
 基于gf框架的token插件,通过服务端验证方式实现token认证;已完全可以支撑线上token认证,并支持集群模式;使用简单,大家可以放心使用;
 
 1. 支持单机gcache和集群gredis模式;
@@ -30,19 +30,99 @@ GlobalMiddleware bool
 * github地址:https://github.com/goflyfox/gtoken
 * gitee地址:https://gitee.com/goflyfox/gtoken
 
-#### gtoken优势
+## gtoken优势
 1. 有效的避免了jwt服务端无法退出问题;
 2. 可以解决jwt无法作废已颁布的令牌;
 3. 用户扩展信息仍存储在服务端,可有效的减少传输空间;
 4. gtoken支撑单点应用使用内存存储,也支持集群使用redis存储;
 5. 支持缓存自动续期,并且不需要客户端进行实现;
 
-#### 安装教程
+## 安装教程
 
 * gopath模式: `go get github.com/goflyfox/gtoken`
 * 或者 使用go.mod添加 :`require github.com/goflyfox/gtoken latest`
 
-#### 使用说明
+## 分组中间件实现
+
+GoFrame官方推荐使用Group方式实现路由和中间件;在`gtoken v1.4.0`版本开始支持分组中间件方式实现,但依然兼容全局中间件实现方式;
+
+### 使用说明
+
+推荐使用分组方式实现
+
+```bash
+	// 启动gtoken
+	gfToken := &gtoken.GfToken{
+		LoginPath:        "/login",
+		LoginBeforeFunc:  loginFunc,
+		LogoutPath:       "/user/logout",
+	}
+	s.Group("/", func(group *ghttp.RouterGroup) {
+		group.Middleware(CORS)
+		gfToken.Middleware(group)
+
+		group.ALL("/system/user", func(r *ghttp.Request) {
+			r.Response.WriteJson(gtoken.Succ("system user"))
+		})
+		………………
+	})
+```
+
+登录方法实现,通过username返回空或者r.ExitAll()\r.Exit()处理认证失败;
+
+```go
+func Login(r *ghttp.Request) (string, interface{}) {
+	username := r.GetPostString("username")
+	passwd := r.GetPostString("passwd")
+
+	// TODO 进行登录校验
+	if username == "" || passwd == "" {
+		r.Response.WriteJson(gtoken.Fail("账号或密码错误."))
+		r.ExitAll()
+	}
+
+	return username, ""
+}
+```
+
+通过`gtoken.GetTokenData(r)`获取登录信息
+
+### 路径拦截规则
+
+```go
+    AuthExcludePaths: g.SliceStr{"/user/info", "/system/user/*"}, // 不拦截路径  /user/info,/system/user/info,/system/user,
+```
+
+1. 分组中间件实现,不需要设置`AuthPaths`认证路径,设置也没有作用,**需要认证路径为分组下所有路由**;
+2. 使用分组拦截的是通过GoFrame的`group.Middleware(authMiddleware)`方法,对该分组下的所有路由进行拦截;
+3. 对登录接口路径`loginPath`做拦截认证放行;
+4. 严格按照GoFrame分组中间件拦截优先级;
+5. 如果配置`AuthExcludePaths`路径,会将不拦截路径排除;
+
+### 逻辑测试
+
+参考sample项目,先运行main.go,然后可运行api_test.go进行测试并查看结果;验证逻辑说明:
+
+1. 访问用户信息,提示未携带token
+2. 调用登录后,携带token访问正常
+3. 调用登出提示成功
+4. 携带之前token访问,提示未登录
+
+```json
+=== RUN   TestAdminSystemUser
+    api_admin_test.go:22: 1. not login and visit user
+    api_admin_test.go:29: {"code":-401,"msg":"请求错误或登录超时","data":""}
+    api_admin_test.go:42: 2. execute login and visit user
+    api_admin_test.go:45: {"code":0,"msg":"success","data":"system user"}
+    api_admin_test.go:51: 3. execute logout
+    api_admin_test.go:54: {"code":0,"msg":"success","data":"Logout success"}
+    api_admin_test.go:60: 4. visit user
+    api_admin_test.go:65: {"code":-401,"msg":"请求错误或登录超时","data":""}
+```
+
+## 全局中间件实现
+
+### 使用说明
 
 只需要配置登录路径、登出路径、拦截路径以及登录校验实现即可
 
@@ -77,7 +157,7 @@ func Login(r *ghttp.Request) (string, interface{}) {
 
 通过`gtoken.GetTokenData(r)`获取登录信息
 
-#### 路径拦截规则
+### 路径拦截规则
 ```go
     AuthPaths:        g.SliceStr{"/user", "/system"},             // 这里是按照前缀拦截,拦截/user /user/list /user/add ...
     AuthExcludePaths: g.SliceStr{"/user/info", "/system/user/*"}, // 不拦截路径  /user/info,/system/user/info,/system/user,
@@ -90,13 +170,13 @@ func Login(r *ghttp.Request) (string, interface{}) {
 4. 程序先处理认证路径,如果满足;再排除不拦截路径;
 5. 如果只想用排除路径功能,将拦截路径设置为`/*`即可;
 
-#### 逻辑测试
+### 逻辑测试
 
-可运行api_test.go进行测试并查看结果;验证逻辑说明:
+参考sample1项目,先运行main.go,然后可运行api_test.go进行测试并查看结果;验证逻辑说明:
 
 1. 访问用户信息,提示未携带token
-2. 登录后,携带token访问正常
-3. 登出成功
+2. 调用登录后,携带token访问正常
+3. 调用登出提示成功
 4. 携带之前token访问,提示未登录
 
 ```json
@@ -110,8 +190,8 @@ func Login(r *ghttp.Request) (string, interface{}) {
     api_test.go:81: 4. visit user
     api_test.go:86: {"code":-401,"msg":"请求错误或登录超时","data":""}
 ```
-#### 返回码
-       
+## 返回码及配置项
+
 1. 正常操作成功返回0
 2. 未登录访问需要登录资源返回401
 3. 程序异常返回-99,如编解码错误等
@@ -122,11 +202,38 @@ FAIL         = -1  // 失败
 ERROR        = -99  // 异常
 UNAUTHORIZED = -401  // 未认证
 ```
-#### 感谢
+### 配置项说明
+
+具体可参考`GfToken`结构体,字段解释如下:
+
+| 名称             | 配置字段         | 说明                                                    | 分组中间件 | 全局中间件 |
+| ---------------- | ---------------- | ------------------------------------------------------- | ---------- | ---------- |
+| 服务名           | ServerName       | 默认空即可                                              | 支持       | 支持       |
+| 缓存模式         | CacheMode        | 1 gcache 2 gredis 默认1                                 | 支持       | 支持       |
+| 缓存key          | CacheKey         | 默认缓存前缀`GToken:`                                   | 支持       | 支持       |
+| 超时时间         | Timeout          | 默认10天(毫秒)                                        | 支持       | 支持       |
+| 缓存刷新时间     | MaxRefresh       | 默认为超时时间的一半(毫秒)                            | 支持       | 支持       |
+| Token分隔符      | TokenDelimiter   | 默认`_`                                                 | 支持       | 支持       |
+| Token加密key     | EncryptKey       | 默认`12345678912345678912345678912345`                  | 支持       | 支持       |
+| 认证失败提示     | AuthFailMsg      | 默认`请求错误或登录超时`                                | 支持       | 支持       |
+| 是否支持多端登录 | MultiLogin       | 默认false                                               | 支持       | 支持       |
+| 中间件类型       | MiddlewareType   | 1、Group 2、Bind 3 、Global;<br>使用分组模式不需要设置 | 支持       | 支持       |
+| 登录路径         | LoginPath        | 登录接口路径                                            | 支持       | 支持       |
+| 登录验证方法     | LoginBeforeFunc  | 登录验证需要用户实现方法                                | 支持       | 支持       |
+| 登录返回方法     | LoginAfterFunc   | 登录完成后调用                                          | 支持       | 支持       |
+| 登出地址         | LogoutPath       | 登出接口路径                                            | 支持       | 支持       |
+| 登出验证方法     | LogoutBeforeFunc | 登出接口前调用                                          | 支持       | 支持       |
+| 登出返回方法     | LogoutAfterFunc  | 登出接口完成后调用                                      | 支持       | 支持       |
+| 拦截地址         | AuthPaths        | 此路径列表进行认证                                      | 不需要     | 支持       |
+| 拦截排除地址     | AuthExcludePaths | 此路径列表不进行认证                                    | 支持       | 支持       |
+| 认证验证方法     | AuthBeforeFunc   | 拦截认证前后调用                                        | 支持       | 支持       |
+| 认证返回方法     | AuthAfterFunc    | 拦截认证完成后调用                                      | 支持       | 支持       |
+
+## 感谢
 
 1. gf框架 [https://github.com/gogf/gf](https://github.com/gogf/gf) 
 
-#### 项目支持
+## 项目支持
 
 - 项目的发展,离不开大家得支持~!~
 

+ 2 - 2
example/sample/config/config.toml

@@ -11,5 +11,5 @@
 
 # Redis数据库配置
 [redis]
-  default = "127.0.0.1:16379,0,soccer"
-  cache   = "127.0.0.1:16379,1,soccer?idleTimeout=600"
+    default = "127.0.0.1:16379,0,soccer"
+    cache   = "127.0.0.1:16379,1,soccer?idleTimeout=600"

+ 1 - 1
example/sample/test/api_admin_test.go

@@ -205,7 +205,7 @@ func TestAdminMultiLogin(t *testing.T) {
 
 	t.Log("token2:" + token2)
 
-	if g.Config().GetBool("gtoken.multi-login") {
+	if g.Config().GetBool("gToken.MultiLogin") {
 		if token1 != token2 {
 			t.Error("error:", "token not same ")
 		}

+ 1 - 1
example/sample/test/api_test.go

@@ -250,7 +250,7 @@ func TestMultiLogin(t *testing.T) {
 
 	t.Log("token2:" + token2)
 
-	if g.Config().GetBool("gtoken.multi-login") {
+	if g.Config().GetBool("gToken.MultiLogin") {
 		if token1 != token2 {
 			t.Error("error:", "token not same ")
 		}

+ 2 - 2
example/sample1/config/config.toml

@@ -22,5 +22,5 @@
 
 # Redis数据库配置
 [redis]
-  default = "127.0.0.1:16379,0,soccer"
-  cache   = "127.0.0.1:16379,1,soccer?idleTimeout=600"
+    default = "127.0.0.1:16379,0,soccer"
+    cache   = "127.0.0.1:16379,1,soccer?idleTimeout=600"

+ 1 - 1
example/sample1/test/api_test.go

@@ -289,7 +289,7 @@ func TestMultiLogin(t *testing.T) {
 
 	t.Log("token2:" + token2)
 
-	if g.Config().GetBool("gtoken.multi-login") {
+	if g.Config().GetBool("gToken.MultiLogin") {
 		if token1 != token2 {
 			t.Error("error:", "token not same ")
 		}

+ 3 - 3
gtoken/gtoken.go

@@ -72,8 +72,8 @@ type GfToken struct {
 	AuthAfterFunc func(r *ghttp.Request, respData Resp)
 }
 
-// Init 初始化
-func (m *GfToken) Init() bool {
+// InitConfig 初始化配置信息
+func (m *GfToken) InitConfig() bool {
 	if m.CacheMode == 0 {
 		m.CacheMode = CacheModeCache
 	}
@@ -180,7 +180,7 @@ func (m *GfToken) Init() bool {
 
 // Start 启动
 func (m *GfToken) Start() bool {
-	if !m.Init() {
+	if !m.InitConfig() {
 		return false
 	}
 	glog.Info("[GToken][params:" + m.String() + "]start... ")

+ 1 - 1
gtoken/gtoken_group.go

@@ -7,7 +7,7 @@ import (
 
 // 绑定group
 func (m *GfToken) Middleware(group *ghttp.RouterGroup) bool {
-	if !m.Init() {
+	if !m.InitConfig() {
 		return false
 	}
 	// 设置为Group模式

+ 2 - 2
gtoken/gtoken_test.go

@@ -161,7 +161,7 @@ func authPath(gfToken *gtoken.GfToken, t *testing.T) {
 func TestEncryptDecryptToken(t *testing.T) {
 	t.Log("encrypt and decrypt token test ")
 	gfToken := gtoken.GfToken{}
-	gfToken.Init()
+	gfToken.InitConfig()
 
 	userKey := "123123"
 	token := gfToken.EncryptToken(userKey, "")
@@ -187,7 +187,7 @@ func TestEncryptDecryptToken(t *testing.T) {
 func BenchmarkEncryptDecryptToken(b *testing.B) {
 	b.Log("encrypt and decrypt token test ")
 	gfToken := gtoken.GfToken{}
-	gfToken.Init()
+	gfToken.InitConfig()
 
 	userKey := "123123"
 	token := gfToken.EncryptToken(userKey, "")