Copyright © 2022-2025 aizws.net · 网站版本: v1.2.6·内部版本: v1.25.2·
页面加载耗时 0.00 毫秒·物理内存 135.0MB ·虚拟内存 1372.6MB
欢迎来到 AI 中文社区(简称 AI 中文社),这里是学习交流 AI 人工智能技术的中文社区。 为了更好的体验,本站推荐使用 Chrome 浏览器。
在每一个服务都做鉴权是一件很麻烦的事情,我们可以通过 go-micro 工具包 micro 中提供的 api 网关来做统一鉴权。
另外,go-micro 在 go-plugins 中提供了 micro 权限插件,但未包含 jwt 形式的鉴权。如果我们需要使用 jwt 鉴权,就必须自行实现相关接口。
接口形式:
type Handler func(http.Handler) http.Handler
接口实现 :
func JWTAuthWrapper(t *token.Token) plugin.Handler {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//不需要登录的url地址 strings.HasPrefix(r.URL.Path, "/hello") ||
if r.URL.Path == "/metrics" ||
r.URL.Path == "/user/login" ||
r.URL.Path == "/user/register" {
h.ServeHTTP(w, r)
return
}
tokenstr := r.Header.Get("Authorization")
userFromToken, e := t.Decode(tokenstr)
if e != nil {
_, _ = w.Write(unauthorized)
return
}
r.Header.Set("X-Example-Username", userFromToken.UserName)
h.ServeHTTP(w, r)
})
}
}
token:
package token
import (
"time"
"log"
"sync"
jwt "github.com/dgrijalva/jwt-go"
config "github.com/micro/go-micro/config"
)
// CustomClaims 自定义的 metadata在加密后作为 JWT 的第二部分返回给客户端
type CustomClaims struct {
UserName string `json:"user_name"`
jwt.StandardClaims
}
// Token jwt服务
type Token struct {
rwlock sync.RWMutex
privateKey []byte
conf config.Config
}
func (srv *Token) get() []byte {
srv.rwlock.RLock()
defer srv.rwlock.RUnlock()
return srv.privateKey
}
func (srv *Token) put(newKey []byte) {
srv.rwlock.Lock()
defer srv.rwlock.Unlock()
srv.privateKey = newKey
}
// InitConfig 初始化
func (srv *Token) InitConfig(address string, path ...string) {
srv.put([]byte("秘钥"))
}
func (srv *Token) enableAutoUpdate(path ...string) {
go func() {
for {
w, err := srv.conf.Watch(path...)
if err != nil {
log.Println(err)
}
v, err := w.Next()
if err != nil {
log.Println(err)
}
value := v.Bytes()
srv.put(value)
log.Println("New JWT privateKey:", string(srv.get()))
}
}()
}
//Decode 解码
func (srv *Token) Decode(tokenStr string) (*CustomClaims, error) {
t, err := jwt.ParseWithClaims(tokenStr, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
return srv.get(), nil
})
if err != nil {
return nil, err
}
// 解密转换类型并返回
if claims, ok := t.Claims.(*CustomClaims); ok && t.Valid {
return claims, nil
}
return nil, err
}
// Encode 将 User 用户信息加密为 JWT 字符串
// expireTime := time.Now().Add(time.Hour * 24 * 3).Unix() 三天后过期
func (srv *Token) Encode(issuer, userName string, expireTime int64) (string, error) {
claims := CustomClaims{
userName,
jwt.StandardClaims{
Issuer: issuer,
IssuedAt: time.Now().Unix(),
ExpiresAt: expireTime,
},
}
jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return jwtToken.SignedString(srv.get())
}
后面就是注册到micro的服务中。
import (
"github.com/micro/micro/plugin"
)
tk := &token.Token{}
_ = plugin.Register(plugin.NewPlugin(
plugin.WithName("auth"),
plugin.WithInit(func(ctx *cli.Context) error {
log.Println(ctx.String("consul_address"))
tk.InitConfig(ctx.String("consul_address"), "micro", "config", "jwt-key", "key")
return nil
}),
plugin.WithHandler(
auth.JWTAuthWrapper(tk),
),
))