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上的官方文档。
贡献
- Fork项目
- 克隆你的fork到本地
- 创建特性分支
- 进行修改并添加
- 提交你的修改
- 推送到分支
- 创建新的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)
}
}
最佳实践
- 生产环境应使用HTTPS保护认证信息
- JWT密钥应足够复杂并定期轮换
- 令牌过期时间应根据应用场景合理设置
- 敏感路由应考虑添加速率限制
- 用户权限应结合RBAC或ABAC模型实现细粒度控制
go-guardian提供了丰富的功能和灵活的扩展性,可以满足现代Web应用和API的各种认证需求。通过组合不同的策略,你可以轻松构建出既安全又易于维护的认证系统。