gogf / gf-jwt Goto Github PK
View Code? Open in Web Editor NEWGoFrame HTTP JWT middleware.
Home Page: https://goframe.org
License: MIT License
GoFrame HTTP JWT middleware.
Home Page: https://goframe.org
License: MIT License
目前只要TOKEN失效都返回的401。如果TOKEN失效·但是在可刷新范围内·是否可以返回其他状态码?
一般在 Authenticator
方法里,还会做表单校验之类的业务,但是 Authenticator
里的所有错误处理都是经过 Unauthorized
方法 , 而 Unauthorized
里所有的 状态码
都是固定的 401,但是表单错误这类的状态码肯定是不能用401的啊 ...
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已经进入了黑名单,无法使用
expire := mw.TimeFunc().Add(mw.Timeout)
newClaims["exp"] = expire.Unix()
newClaims["orig_iat"] = mw.TimeFunc().Unix()
tokenString, err := mw.signedString(newToken)
@mingzaily 我在 v2 分支上面更新了 jwt 的版本,你帮忙看看还有什么问题没有哈!
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
如题,需要根据两种情况作出不同的反应。
尝试过fork下来,改了以后 go get 自己的,但是会报错 unexpected module path
首先感觉作者能够开源这么好的框架和插件给大家使用!!
我看了一下作者的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?
目前gf-jwt默认是将md5(token)作为KEY,建议可以加KEY前缀,自定义KEY等
在依赖包中发现被墙的包:
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
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
}
添加上auth_jwt.go
上面这句 后 世界恢复和平
token失效过期后,调用refreshtoken接口刷新token,接口依然会检测过期
mw.CheckIfTokenExpire(ctx)
或许是否存在遗漏的流程?
如果自己定义错误的消息提示,现在的提示都在auth_jwt文件中
目前黑名单采用的GoFrame的blacklist = gcache.New()
,这个方法采用的是内存缓存。是否可以支持配置采用redis进行缓存呢。
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 还有效 并没有退出登陆
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.