example/api/auth.go


配置名类型默认值说明
1Realmstring"test zhou"用户的领域名称,必传
2SigningAlgorithmstringHS256签名算法-可能的值为HS256、HS384、HS512,可选,默认值为HS256
3Key[]byte[]byte("secret key")jwt第三部分签名所需的密钥,类型laravel中的JWT_KEY
4Timeouttime.Durationtime.Minute * 5token过期时间
5MaxRefreshtime.Durationtime.Minute * 5token过期后,可凭借旧token获取新token的刷新时间
6IdentityKeystring"id"身份验证的key值
7TokenLookupstring"header: Authorization, query: token, cookie: jwt"token检索模式,用于提取token-> Authorization
8TokenHeadNamestring"Bearer"token在请求头时的名称,默认值为Bearer.客户端在header中传入"Authorization":"Bearer xxxxxx"
9TimeFuncfunc()time.Now设置JWT的时区
10Authenticatorfunc()
根据登录信息对用户进行身份验证的回调函数
11LoginResponsefunc()
完成登录后返回的信息,用户可自定义返回数据
12RefreshResponsefunc()
刷新token后返回的信息,用户可自定义返回数据
13LogoutResponsefunc()
token无效化(黑名单)处理后返回的信息,用户可自定义返回数据
14Unauthorizedfunc()
处理不进行授权的逻辑
15IdentityHandlerfunc()
解析并设置用户身份信息,并设置身份信息至每次请求中
16PayloadFuncfunc()
登录期间的设置私有载荷的函数,默认设置Authenticator函数回调的所有内容
17CacheAdapter

gcache.Adapter


设置黑名单的缓存机制,默认为内存缓存,可修改为Redis缓存

函数说明

Authenticator

负责进行身份验证的回调函数,回调必须携带身份验证的键值对,如IdentityKey: "id",则身份认证回调函数应当包含{"id": 1}

func Authenticator(r *ghttp.Request) (interface{}, error) {
	var (
		apiReq     *model.ApiLoginReq
		serviceReq *model.ServiceLoginReq
	)
	if err := r.Parse(&apiReq); err != nil {
		return "", err
	}
	if err := gconv.Struct(apiReq, &serviceReq); err != nil {
		return "", err
	}
	
	// user {"id": 1, "username": "admin"}
	if user := service.User.GetUserByUsernamePassword(serviceReq); user != nil {
		return user, nil
	}

	return nil, jwt.ErrFailedAuthentication
}

LoginResponse

登录成功后返回的信息,可自定义

// LoginResponse is used to define customized login-successful callback function.
func LoginResponse(r *ghttp.Request, code int, token string, expire time.Time) {
	r.Response.WriteJson(g.Map{
		"code":   http.StatusOK,
		"token":  token,
		"expire": expire.Format(time.RFC3339),
	})
	r.ExitAll()
}

RefreshResponse

刷新成功后返回的信息,可自定义

func RefreshResponse(r *ghttp.Request, code int, token string, expire time.Time) {
	r.Response.WriteJson(g.Map{
		"code":   http.StatusOK,
		"token":  token,
		"expire": expire.Format(time.RFC3339),
	})
	r.ExitAll()
}

LogoutResponse

推出成功后返回的信息,可自定义

func LogoutResponse(r *ghttp.Request, code int) {
	r.Response.WriteJson(g.Map{
		"code":    code,
		"message": "success",
	})
	r.ExitAll()
}

Unauthorized

授权失败(如账号密码错误,刷新失败,token过期等)后返回的信息,可自定义

func Unauthorized(r *ghttp.Request, code int, message string) {
	r.Response.WriteJson(g.Map{
		"code": code,
		"msg":  message,
	})
	r.ExitAll()
}

PayloadFunc

载荷Payload由预定义exp(过期时间),iat(签发时间)和私有载荷组成,详情请看jwt扩展阅读

该函数作用是自定义私有Payload,默认是将Authenticator函数返回的map[string]interface循环放入载荷中

示例代码,参数data断言为map[string]interface,因此Authenticator也应当返回map[string]interface

在登录后的,开发者可以使用r.Get("JWT_PAYLOAD")获取Payload

// PayloadFunc is a callback function that will be called during login.
// Using this function it is possible to add additional payload data to the webtoken.
// The data is then made available during requests via c.Get("JWT_PAYLOAD").
// Note that the payload is not encrypted.
// The attributes mentioned on jwt.io can't be used as keys for the map.
// Optional, by default no additional data will be set.
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

函数作用是从每次的请求中取得解析Payload,并设置为每次请求设置身份标识

如果IdentityKey设置为id,则开发者可以用r.GetParma("id")获取用户id

// IdentityHandler get the identity from JWT and set the identity for every request
// Using this function, by r.GetParam("id") get identity
func IdentityHandler(r *ghttp.Request) interface{} {
	claims := jwt.ExtractClaims(r)
	return claims[Auth.IdentityKey]
}
  • No labels

8 Comments

  1. IdentityKey 这个参数名会覆盖请求的同名参数值?

  2. IdentityKey  竟然会覆盖同名参数...

  3. 既然会覆盖,demo的例子还是别用id了吧,改个ctxUserId都好呀。
    接口传id的概率可以说是百分百了。
    这还不是每次都覆盖,是测着测着发现被覆盖了。

  4. token生成以后可以放redis么

    1. li

      这个token不是返回给前端存储的么,服务端存他干啥

  5. // Authenticator is used to validate login parameters.
    // It must return user data as user identifier, it will be stored in Claim Array.
    // if your identityKey is 'id', your user data must have 'id'
    // Check error (e) to determine the appropriate error message.
    func Authenticator(ctx context.Context) (any, error) {
    	var (
    		r  = g.RequestFromCtx(ctx)
    		in = entity.User{}
    	)
    	var user entity.User
    	var err error
    	if err = r.Parse(&in); err != nil {
    		return nil, err
    	}
    
    	if user, err = service.User().Login(ctx, in); err == nil {
    		res := gconv.Map(user)
    		id := res["id"]
    		res["identity"] = id
    		return res, nil
    	}
    
    	return nil, jwt.ErrFailedAuthentication
    }

    使用这个IdentityKey  就可以解决同名参数覆盖问题