golang实现现代API和Web认证的插件库go-guardian的使用

Golang实现现代API和Web认证的插件库go-guardian的使用

概述

Go-Guardian是一个Golang库,提供了一种简单、清晰且符合语言习惯的方式来创建强大的现代API和Web认证。它的唯一目的是通过一组可扩展的认证方法(称为策略)来认证请求。

安装

使用以下命令安装最新版本的库:

go get github.com/shaj13/go-guardian/v2

然后在你的应用中引入:

import "github.com/shaj13/go-guardian/v2"

为什么选择Go-Guardian?

  • 提供简单、清晰且符合语言习惯的API
  • 提供主流和传统认证方法
  • 提供基于RFC-4226和RFC-6238的双因素认证和一次性密码
  • 提供定制策略的机制,甚至可以编写自定义策略

策略

Go-Guardian支持多种认证策略,包括但不限于:

  • JWT
  • Opaque(服务器端一致性令牌)
  • Oauth2-JWT
  • Oauth2-Introspection
  • Oauth2-OpenID-userinfo
  • OpenID-IDToken
  • Kubernetes (Token Review)
  • 2FA
  • 基于证书的认证
  • Bearer-Token
  • Static-Token
  • LDAP
  • Basic认证
  • Digest认证
  • Union策略

示例代码

基本认证示例

package main

import (
	"fmt"
	"net/http"
	
	"github.com/shaj13/go-guardian/v2/auth"
	"github.com/shaj13/go-guardian/v2/auth/strategies/basic"
	"github.com/shaj13/go-guardian/v2/auth/strategies/union"
)

// 验证用户凭据的函数
func validateUser(ctx context.Context, r *http.Request, userName, password string) (auth.Info, error) {
	// 这里应该是你的用户验证逻辑
	// 示例中我们使用硬编码的用户名和密码
	if userName == "admin" && password == "admin" {
		return auth.NewDefaultUser("admin", "1", nil, nil), nil
	}
	return nil, fmt.Errorf("invalid credentials")
}

func main() {
	// 创建基本认证策略
	basicStrategy := basic.New(validateUser)
	
	// 创建联合策略(可以组合多个策略)
	strategy := union.New(basicStrategy)
	
	// 创建HTTP处理器
	http.HandleFunc("/v1/auth", func(w http.ResponseWriter, r *http.Request) {
		// 认证请求
		user, err := strategy.Authenticate(r.Context(), r)
		if err != nil {
			code := http.StatusUnauthorized
			http.Error(w, http.StatusText(code), code)
			return
		}
		
		// 认证成功,返回欢迎信息
		fmt.Fprintf(w, "Welcome %s", user.GetUserName())
	})
	
	// 启动HTTP服务器
	http.ListenAndServe(":8080", nil)
}

JWT认证示例

package main

import (
	"fmt"
	"net/http"
	"time"
	
	"github.com/shaj13/go-guardian/v2/auth"
	"github.com/shaj13/go-guardian/v2/auth/strategies/jwt"
	"github.com/shaj13/go-guardian/v2/auth/strategies/union"
	"github.com/shaj13/go-guardian/v2/auth/strategies/basic"
	"github.com/shaj13/libcache"
	_ "github.com/shaj13/libcache/lru"
)

var strategy union.Union
var jwtStrategy jwt.Strategy

func validateUser(ctx context.Context, r *http.Request, userName, password string) (auth.Info, error) {
	// 在实际应用中,这里应该查询数据库验证用户
	if userName == "admin" && password == "admin" {
		return auth.NewDefaultUser("admin", "1", nil, nil), nil
	}
	return nil, fmt.Errorf("invalid credentials")
}

func main() {
	// 设置JWT配置
	cfg := &jwt.Config{
		SigningKey: []byte("secret-key"), // 用于签名JWT的密钥
		ExpDuration: time.Hour * 24,      // token过期时间
	}
	
	// 创建缓存
	cache := libcache.LRU.New(0)
	
	// 创建JWT策略
	jwtStrategy = jwt.New(cache, cfg)
	
	// 创建基本认证策略
	basicStrategy := basic.New(validateUser)
	
	// 创建联合策略
	strategy = union.New(jwtStrategy, basicStrategy)
	
	// 登录端点 - 使用基本认证获取JWT token
	http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
		user, err := basicStrategy.Authenticate(r.Context(), r)
		if err != nil {
			code := http.StatusUnauthorized
			http.Error(w, http.StatusText(code), code)
			return
		}
		
		// 为用户生成JWT token
		token, err := jwtStrategy.Issue(r.Context(), user)
		if err != nil {
			code := http.StatusInternalServerError
			http.Error(w, http.StatusText(code), code)
			return
		}
		
		// 返回token给客户端
		w.Write([]byte(token))
	})
	
	// 受保护端点 - 需要有效的JWT token
	http.HandleFunc("/protected", func(w http.ResponseWriter, r *http.Request) {
		user, err := jwtStrategy.Authenticate(r.Context(), r)
		if err != nil {
			code := http.StatusUnauthorized
			http.Error(w, http.StatusText(code), code)
			return
		}
		
		fmt.Fprintf(w, "Welcome %s", user.GetUserName())
	})
	
	http.ListenAndServe(":8080", nil)
}

文档

更多详细文档和示例可以参考GoDoc上的官方文档。

贡献

  1. Fork项目
  2. 克隆你的fork到本地
  3. 创建特性分支
  4. 进行修改并添加
  5. 提交你的修改
  6. 推送到分支
  7. 创建新的pull request

许可证

Go-Guardian使用MIT许可证发布。


更多关于golang实现现代API和Web认证的插件库go-guardian的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现现代API和Web认证的插件库go-guardian的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用go-guardian实现现代API和Web认证

go-guardian是一个强大的Go语言认证库,专门为现代API和Web应用程序设计。它支持多种认证策略,包括基本认证、JWT、OAuth2等,并提供了灵活的中间件集成方式。

安装go-guardian

go get github.com/shaj13/go-guardian/v2

基本使用示例

1. 基本认证

package main

import (
	"fmt"
	"net/http"
	
	"github.com/shaj13/go-guardian/v2/auth"
	"github.com/shaj13/go-guardian/v2/auth/strategies/basic"
	"github.com/shaj13/go-guardian/v2/auth/strategies/union"
)

func main() {
	// 创建认证策略
	strategy := basic.New(validateUser, "example-realm")

	// 创建HTTP服务器
	http.HandleFunc("/protected", middleware(strategy, protectedHandler))
	fmt.Println("Server started at :8080")
	http.ListenAndServe(":8080", nil)
}

// 验证用户凭据
func validateUser(ctx context.Context, r *http.Request, userName, password string) (auth.Info, error) {
	// 这里应该是从数据库或其他存储中验证用户
	if userName == "admin" && password == "admin123" {
		return auth.NewDefaultUser("admin", "1", nil, nil), nil
	}
	return nil, fmt.Errorf("invalid credentials")
}

// 中间件函数
func middleware(strategy union.Strategy, next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		_, user, err := strategy.AuthenticateRequest(r)
		if err != nil {
			code := http.StatusUnauthorized
			http.Error(w, http.StatusText(code), code)
			return
		}
		
		// 将用户信息存入上下文
		r = auth.RequestWithUser(user, r)
		next(w, r)
	}
}

// 受保护的处理程序
func protectedHandler(w http.ResponseWriter, r *http.Request) {
	user := auth.UserFromCtx(r.Context())
	fmt.Fprintf(w, "Welcome %s\n", user.GetUserName())
}

2. JWT认证

package main

import (
	"fmt"
	"net/http"
	"time"
	
	"github.com/shaj13/go-guardian/v2/auth"
	"github.com/shaj13/go-guardian/v2/auth/strategies/jwt"
	"github.com/shaj13/go-guardian/v2/auth/strategies/union"
	"github.com/shaj13/go-guardian/v2/auth/strategies/token"
)

var authenticator union.Union

func main() {
	// 设置JWT策略
	secret := []byte("your-secret-key")
	opts := []jwt.Option{
		jwt.SetExpDuration(time.Hour),
		jwt.SetSignatureAlgorithm(jwt.HS256),
	}
	
	jwtStrategy := jwt.New(secret, opts...)
	authenticator = union.New(jwtStrategy)
	
	// 登录路由
	http.HandleFunc("/login", loginHandler)
	
	// 受保护路由
	http.HandleFunc("/protected", middleware(authenticator, protectedHandler))
	
	fmt.Println("Server started at :8080")
	http.ListenAndServe(":8080", nil)
}

func loginHandler(w http.ResponseWriter, r *http.Request) {
	// 验证用户凭据
	user := auth.NewDefaultUser("admin", "1", nil, nil)
	
	// 生成JWT令牌
	token, err := jwt.IssueAccessToken(user, []byte("your-secret-key"))
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	
	// 返回令牌给客户端
	w.Write([]byte(token))
}

func middleware(strategy union.Union, next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		_, user, err := strategy.AuthenticateRequest(r)
		if err != nil {
			code := http.StatusUnauthorized
			http.Error(w, http.StatusText(code), code)
			return
		}
		
		r = auth.RequestWithUser(user, r)
		next(w, r)
	}
}

func protectedHandler(w http.ResponseWriter, r *http.Request) {
	user := auth.UserFromCtx(r.Context())
	fmt.Fprintf(w, "Welcome %s\n", user.GetUserName())
}

3. 多策略组合认证

package main

import (
	"fmt"
	"net/http"
	"time"
	
	"github.com/shaj13/go-guardian/v2/auth"
	"github.com/shaj13/go-guardian/v2/auth/strategies/basic"
	"github.com/shaj13/go-guardian/v2/auth/strategies/jwt"
	"github.com/shaj13/go-guardian/v2/auth/strategies/union"
)

func main() {
	// 创建基本认证策略
	basicStrategy := basic.New(validateUser, "example-realm")
	
	// 创建JWT策略
	secret := []byte("your-secret-key")
	jwtOpts := []jwt.Option{
		jwt.SetExpDuration(time.Hour * 24),
		jwt.SetSignatureAlgorithm(jwt.HS256),
	}
	jwtStrategy := jwt.New(secret, jwtOpts...)
	
	// 组合策略
	authenticator := union.New(basicStrategy, jwtStrategy)
	
	http.HandleFunc("/protected", middleware(authenticator, protectedHandler))
	fmt.Println("Server started at :8080")
	http.ListenAndServe(":8080", nil)
}

// 其他函数与前面示例相同...

高级特性

1. 缓存策略

import (
	"github.com/shaj13/go-guardian/v2/auth"
	"github.com/shaj13/go-guardian/v2/auth/strategies/basic"
	"github.com/shaj13/go-guardian/v2/auth/strategies/union"
	"github.com/shaj13/go-guardian/v2/auth/strategies/cache"
)

func main() {
	// 创建基本策略
	basicStrategy := basic.New(validateUser, "example-realm")
	
	// 添加缓存
	cacheStrategy := cache.New(basicStrategy, cache.LRU(1000))
	
	// 组合策略
	authenticator := union.New(cacheStrategy)
	
	// 其他代码...
}

2. 自定义令牌解析

func middleware(strategy union.Union, next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 从自定义位置获取令牌
		token := r.Header.Get("X-Auth-Token")
		if token == "" {
			token = r.URL.Query().Get("token")
		}
		
		// 创建临时请求进行认证
		tmpReq := r.Clone(context.Background())
		if token != "" {
			tmpReq.Header.Set("Authorization", "Bearer "+token)
		}
		
		_, user, err := strategy.AuthenticateRequest(tmpReq)
		if err != nil {
			code := http.StatusUnauthorized
			http.Error(w, http.StatusText(code), code)
			return
		}
		
		r = auth.RequestWithUser(user, r)
		next(w, r)
	}
}

最佳实践

  1. 生产环境应使用HTTPS保护认证信息
  2. JWT密钥应足够复杂并定期轮换
  3. 令牌过期时间应根据应用场景合理设置
  4. 敏感路由应考虑添加速率限制
  5. 用户权限应结合RBAC或ABAC模型实现细粒度控制

go-guardian提供了丰富的功能和灵活的扩展性,可以满足现代Web应用和API的各种认证需求。通过组合不同的策略,你可以轻松构建出既安全又易于维护的认证系统。

回到顶部