Giter VIP home page Giter VIP logo

gf-jwt's People

Contributors

ansionfor avatar crisis111 avatar gqcn avatar mingzaily avatar stardemo avatar yss930819 avatar ywtywt337 avatar zhaopengme avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gf-jwt's Issues

插件里的unauthorized方法的code状态码能不能不固定死?

一般在 Authenticator 方法里,还会做表单校验之类的业务,但是 Authenticator 里的所有错误处理都是经过 Unauthorized 方法 , 而 Unauthorized 里所有的 状态码 都是固定的 401,但是表单错误这类的状态码肯定是不能用401的啊 ...

返回请求header有问题

648行代码是加在请求的header里,等价r.Request.Header.Set()
r.Header.Set("WWW-Authenticate", "JWT realm="+mw.Realm)
使用r.Response.Header().Set()方法才是加在返回请求的header里
r.Response.Header().Set("WWW-Authenticate", "JWT realm="+mw.Realm)

如何返回刷新令牌与刷新过期时间

设置 token 有效期五分钟 最大刷新时间 30 分钟,通过中间件检测当token过期,但是刷新时间还在有效期内自动刷新返回新的token如何实现,看auth_jwt.go里面没有这方面的判断只校验了token过期就直接抛401返回token过期了

刷新Token可能获得与上次相同的Token

看源码刷新Token的机制中,签发时间和过期时间都是秒级时间戳,目前测试的表现是:

  1. 如果在登录后一秒内刷新Token,会得到相同的Token,无法使用
  2. 如果在刷新Token后的一秒内再次刷新Token,也会得到相同的Token,也无法使用

以上两种情况会导致,得到的Token已经进入了黑名单,无法使用

expire := mw.TimeFunc().Add(mw.Timeout)
newClaims["exp"] = expire.Unix()
newClaims["orig_iat"] = mw.TimeFunc().Unix()
tokenString, err := mw.signedString(newToken)

SendCookie Expires time.Duration(maxage)*time.Millisecond

if mw.SendCookie { maxage := int64(expire.Unix() - time.Now().Unix()) r.Cookie.SetCookie(mw.CookieName, tokenString, mw.CookieDomain, "/", time.Duration(maxage)*time.Millisecond) }

maxage 是总秒数,
是不是考虑改为: time.Duration(maxage)*time.Second

这一段代码是表示 user路径下的所有方法都需要鉴权吗? 请关闭吧,我自己测试了

首先感觉作者能够开源这么好的框架和插件给大家使用!!
我看了一下作者的DEMO
有一个疑问
s.Group("/user").Bind("/user", []ghttp.GroupItem{ {"ALL", "*", authHook, ghttp.HOOK_BEFORE_SERVE}, {"GET", "/refresh_token", auth.GfJWTMiddleware.RefreshHandler}, {"GET", "/hello", hello}, })
这一段代码是表示 user路径下的所有方法都需要鉴权吗?
然后可以自动刷新 token?

处理第三方包依赖 google.golang.org/appengine

在依赖包中发现被墙的包:

go: google.golang.org/[email protected]: unrecognized import path "google.golang.org/appengine" (https fetch: Get https://google.golang.org/appengine?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
go: error loading module requirements

为方便开发者调用,考虑一下使用gf框架使用third目录的方式,将所有依赖包加入进项目,并批量替换包引入路径。

开启jwt后 原先正常的路由变404

开启jwt后 原先正常的路由变404

package middle

import (
	jwt "github.com/gogf/gf-jwt"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/os/glog"
	"github.com/gogf/gf/util/gvalid"
	"time"
)

var (
	// 底层JWT中间件。
	GfJWTMiddleware *jwt.GfJWTMiddleware
	// 自定义登录参数验证规则。
	ValidationRules = g.Map{
		"username": "required",
		"password": "required",
	}
)

// 初始化函数,
// 重写此函数以自定义您自己的JWT设置.
func init() {
	authMiddleware, err := jwt.New(&jwt.GfJWTMiddleware{
		Realm:         "test zone",
		Key:           []byte("secret key"),
		Timeout:       time.Minute * 5,
		MaxRefresh:    time.Minute * 5,
		IdentityKey:   "id",
		TokenLookup:   "header: Authorization, query: token, cookie: jwt",
		TokenHeadName: "Bearer",
		TimeFunc:      time.Now,
		//Authenticator:   (&api.MemberController{}).Authenticator, //这里我在router中覆写
		LoginResponse:   LoginResponse,
		RefreshResponse: RefreshResponse,
		Unauthorized:    Unauthorized,
		IdentityHandler: IdentityHandler,
		PayloadFunc:     PayloadFunc,
		CookieHTTPOnly:  true,
	})
	if err != nil {
		glog.Fatal("JWT Error:" + err.Error())
	}
	GfJWTMiddleware = authMiddleware
}

//PayloadFunc是在登录期间调用的回调函数。
//使用此函数可以向webtoken添加其他负载数据。
//然后通过c.Get(“JWT_PAYLOAD”)在请求期间提供数据。
//请注意,有效负载未加密。
//jwt.io中提到的属性不能用作映射的键。
//可选,默认情况下不设置其他数据。
func PayloadFunc(data interface{}) jwt.MapClaims {
	claims := jwt.MapClaims{}
	params := data.(map[string]interface{})
	if len(params) > 0 {
		for k, v := range params {
			claims[k] = v
		}
	}
	return claims
}

// IdentityHandler设置JWT的标识。
func IdentityHandler(r *ghttp.Request) interface{} {
	claims := jwt.ExtractClaims(r)
	return claims["id"]
}

// Unauthorized用于定义自定义的Unauthorized回调函数。
func Unauthorized(r *ghttp.Request, code int, message string) {
	r.Response.WriteJson(g.Map{
		"isSuccess": false,
		"errMsg":    message,
	})
}

// LoginResponse用于定义自定义的登录成功回调函数。
func LoginResponse(r *ghttp.Request, code int, token string, expire time.Time) {
	r.Response.WriteJson(g.Map{
		"isSuccess": true,
		"data": g.Map{
			"token":  token,
			"expire": expire.Format(time.RFC3339),
		},
	})
}

// RefreshResponse用于获取新令牌,无论当前令牌是否过期.
func RefreshResponse(r *ghttp.Request, code int, token string, expire time.Time) {
	r.Response.WriteJson(g.Map{
		"isSuccess": true,
		"data": g.Map{
			"token":  token,
			"expire": expire.Format(time.RFC3339),
		},
	})
}

//身份验证器用于验证登录参数。
//它必须返回用户数据作为用户标识符,它将存储在声明数组中。
//检查错误(e)以确定适当的错误消息。
func Authenticator(r *ghttp.Request) (interface{}, error) {
	data := r.GetMap()
	if e := gvalid.CheckMap(data, ValidationRules); e != nil {
		return "", jwt.ErrFailedAuthentication
	}
	if data["username"] == "admin" && data["password"] == "admin" {
		return g.Map{
			"username": data["username"],
			"id":       data["username"], //require!!!
			"role":     "user",
		}, nil
	}
	return nil, jwt.ErrFailedAuthentication
}

在gf router 启用后 访问正常路由会404
image

image

image

添加上auth_jwt.go上面这句 后 世界恢复和平

blacklist的存放问题

目前黑名单采用的GoFrame的blacklist = gcache.New(),这个方法采用的是内存缓存。是否可以支持配置采用redis进行缓存呢。

LogoutHandler 好像存在一个bug

func (mw *GfJWTMiddleware) LogoutHandler(ctx context.Context) {
r := g.RequestFromCtx(ctx)

// delete auth cookie
if mw.SendCookie {
	r.Cookie.SetCookie(mw.CookieName, "", mw.CookieDomain, "/", -1)
}

claims, token, err := mw.CheckIfTokenExpire(ctx)
if err != nil {
	mw.unauthorized(ctx, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(err, ctx))
	return
}

err = mw.setBlacklist(ctx, token, claims)

if err != nil {
	mw.unauthorized(ctx, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(err, ctx))
	return
}

return

}

当只有 cookie 存在token 时 此处先把cookie 给清了 导致 一直401 实际token 还有效 并没有退出登陆

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.