verifier

package module
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 14, 2023 License: MIT Imports: 6 Imported by: 0

README

verifier

Golang JWT token verifier with storage

You can use github.com/xandercheung/verifier-redis-storage as token storage, or create new storage to implement TokenStorage interface

Usage

go get -u github.com/NoahCodeGG/verifier
Find example in example/verifier_example.go
package main

import (
	"fmt"
	"time"

	"github.com/NoahCodeGG/verifier"
	"github.com/go-redis/redis/v8"
	storage "github.com/xandercheung/verifier-redis-storage"
)

func main() {
	// you can create new TokenStorage
	// use github.com/xandercheung/verifier-redis-storage(github.com/go-redis/redis/v8) as token storage,
	// init your redisClient
	redisClient := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Username: "",
		Password: "",
		DB:       0,
	})
	tokenStorage := storage.RedisStorage{Cli: redisClient}

	// use default verifier
	verifier.InitDefaultVerifier(
		"your key",
		&tokenStorage,
		// options
		verifier.WithSourceName("user"),                   // default "user"
		verifier.WithTokenExpireDuration(10*time.Minute),  // default 15 minutes
		verifier.WithAuthExpireDuration(2*time.Hour),      // default 3 hours
		verifier.WithTempTokenExpireDuration(time.Minute), // default 30 seconds
	)

	// or creates a new Verifier
	// v := verifier.New(
	//	"your key",
	//	&tokenStorage,
	//	verifier.WithTempTokenExpireDuration(time.Minute),
	// )

	sourceId := uint(1)
	token, err := verifier.CreateToken(sourceId, map[string]interface{}{"foo": "bar"})
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(token)

	// verify token and refresh token(if necessary)
	claims, newToken, err := verifier.VerifyToken(token)
	if err != nil {
		// validation failed
		fmt.Println(err)
	}
	fmt.Println(claims)
	fmt.Println(newToken)

	// verify token only
	claims, isAuthorized := verifier.IsTokenAuthorized(token)
	fmt.Println(claims)
	fmt.Println(isAuthorized)

	// destroy token by sourceId and uuid
	err = verifier.DestroyToken(sourceId, claims.UUID)
	if err != nil {
		fmt.Println(err)
	}

	// destroy all token of sourceId
	err = verifier.DestroyAllToken(sourceId)
	if err != nil {
		fmt.Println(err)
	}

	// refresh token manually
	newToken, err = verifier.RefreshToken(claims.SourceID, claims.UUID, claims.Data)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(newToken)
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	TokenInvalidError = errors.New("invalid token")
)

Functions

func CompareHashAndPassword

func CompareHashAndPassword(hashedPassword, password string) error

CompareHashAndPassword compares a bcrypt hashed password with its possible plaintext equivalent. Returns nil on success, or an error on failure.

func CreateToken

func CreateToken(sourceID any, data map[string]interface{}) (string, error)

CreateToken 创建新 token data 为自定义数据

func DestroyAllToken

func DestroyAllToken(sourceID any) error

DestroyAllToken 销毁 sourceID 的所有 token

func DestroyToken

func DestroyToken(sourceID any, uid string) error

DestroyToken 销毁 token

func GenerateHashedPassword

func GenerateHashedPassword(password string) (string, error)

GenerateHashedPassword returns the bcrypt hash of the password

func InitDefaultVerifier

func InitDefaultVerifier(jwtKey string, tokenStorage TokenStorage, options ...Option)

func RefreshToken

func RefreshToken(sourceID any, uid string, data map[string]interface{}) (string, error)

RefreshToken 刷新 token (根据原有的 sourceID 和 uuid) data 为自定义数据

Types

type CustomClaims

type CustomClaims struct {
	*jwt.RegisteredClaims
	SourceID any
	UUID     string                 // source_id 与 随机 uuid 组合,允许同一账号多次登录
	Data     map[string]interface{} // 自定义数据
}

func IsTokenAuthorized

func IsTokenAuthorized(tokenStr string) (CustomClaims, bool)

IsTokenAuthorized token 是否通过身份验证(仅验证)

func VerifyToken

func VerifyToken(tokenStr string) (CustomClaims, string, error)

VerifyToken 验证 token (包含刷新 token 逻辑)

func (*CustomClaims) IsParamsValid

func (c *CustomClaims) IsParamsValid() bool

type Option

type Option interface {
	Apply(*Verifier)
}

An Option configures a verifier.

func WithAuthExpireDuration

func WithAuthExpireDuration(duration time.Duration) Option

WithAuthExpireDuration can be used to set authExpireDuration.

func WithJwtTimeFunc

func WithJwtTimeFunc(timeFunc func() time.Time) Option

WithJwtTimeFunc can be used to set jwtTimeFunc.

func WithSourceName

func WithSourceName(sourceName string) Option

WithSourceName can be used to set sourceName.

func WithTempTokenExpireDuration

func WithTempTokenExpireDuration(duration time.Duration) Option

WithTempTokenExpireDuration can be used to set tempTokenExpireDuration.

func WithTokenExpireDuration

func WithTokenExpireDuration(duration time.Duration) Option

WithTokenExpireDuration can be used to set tokenExpireDuration.

type OptionFunc

type OptionFunc func(*Verifier)

OptionFunc is a function that configures a verifier.

func (OptionFunc) Apply

func (f OptionFunc) Apply(verifier *Verifier)

Apply calls f(verifier)

type TokenStorage

type TokenStorage interface {
	Get(key string) (string, error) // return error when key does not exist
	Set(key string, value interface{}, expiration time.Duration) error
	SetNX(key string, value interface{}, expiration time.Duration) bool
	Del(key string) error
	DelByKeyPrefix(keyPrefix string) error
	Exists(key string) bool
}

TokenStorage token 存储器

type Verifier

type Verifier struct {
	// contains filtered or unexported fields
}

Verifier token 验证器 * token 生成和验证逻辑:

实现效果: 无操作后 3 小时自动退出,token 每 15 分钟刷新一次

token 生成逻辑:

根据 sourceID 和 uuid 生成,token 过期时间为 15 分钟
并以 sourceID 和 uuid 组合 为 key(keyA), token 为值 记录到存储器, 过期时间设置为 3 小时

验证 token 逻辑:

	大前提: keyA 存在于存储器, 不存在则不通过验证

	1. jwt 解析 token 没有 error
		=> token 有效 并且 存储器 中 (keyA) 对应的值 和 token 相同, 则通过验证
	2. jwt 解析 token 有 error, 且 error 为 token 过期
        => 1. token 与 存储器中 (keyA) 对应的值相同, 刷新 token, 通过验证并返回新 token
		=> 2. 当前 token 已被存储器记录(作为过渡token), 通过验证
	3. 其他情况,不通过验证

PS: 刷新 token 时,将旧 token 记录到存储器 原因:

并发请求时,只允许一个线程刷新 token,在新 token 未返回客户端前,短时间内允许旧 token 请求

func DefaultVerifierVerifier

func DefaultVerifierVerifier() *Verifier

func New

func New(jwtKey string, tokenStorage TokenStorage, options ...Option) *Verifier

func (*Verifier) CreateToken

func (v *Verifier) CreateToken(sourceID any, data map[string]interface{}) (string, error)

CreateToken 创建新 token data 为自定义数据

func (*Verifier) DestroyAllToken

func (v *Verifier) DestroyAllToken(sourceID any) error

DestroyAllToken 销毁 sourceID 的所有 token

func (*Verifier) DestroyToken

func (v *Verifier) DestroyToken(sourceID any, uid string) error

DestroyToken 销毁 token

func (*Verifier) IsTokenAuthorized

func (v *Verifier) IsTokenAuthorized(tokenStr string) (CustomClaims, bool)

IsTokenAuthorized token 是否通过身份验证(仅验证)

func (*Verifier) RefreshToken

func (v *Verifier) RefreshToken(sourceID any, uid string, data map[string]interface{}) (string, error)

RefreshToken 刷新 token (根据原有的 sourceID 和 uuid) data 为自定义数据

func (*Verifier) VerifyToken

func (v *Verifier) VerifyToken(tokenStr string) (CustomClaims, string, error)

VerifyToken 验证 token (包含刷新 token 逻辑) 若刷新了 token 则返回新 token 若返回 error 则说明未通过验证

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL