golang基于JWT的多后端认证登录微服务插件loginsrv的使用
Golang基于JWT的多后端认证登录微服务插件loginsrv的使用
loginsrv是一个独立的简约登录服务器,为多个登录后端提供JWT登录功能。
功能概述
loginsrv提供最小化的认证端点,登录通过提供者执行并返回JSON Web Token(JWT)。它可以作为:
- 独立微服务
- Docker容器
- Golang库
- Caddy插件
支持的提供者后端
支持以下提供者(登录后端):
- Htpasswd
- OSIAM
- Simple (通过配置的用户/密码对)
- Httpupstream
- OAuth2
- GitHub登录
- Google登录
- Bitbucket登录
- Facebook登录
- Gitlab登录
配置和启动
配置选项
所有配置选项也可以通过环境变量设置,格式为LOGINSRV_OPTION_NAME
。例如jwt-secret
可以通过环境变量LOGINSRV_JWT_SECRET
设置。
启动示例
使用loginsrv最简单的方式是通过提供的docker容器。例如使用simple提供者配置:
$ docker run -d -p 8080:8080 tarent/loginsrv -cookie-secure=false -jwt-secret my_secret -simple bob=secret
$ curl --data "username=bob&password=secret" 127.0.0.1:8080/login
eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJib2IifQ.uWoJkSXTLA_RvfLKe12pb4CyxQNxe5_Ovw-N5wfQwkzXz2enbhA9JZf8MmTp9n-TTDcWdY3Fd1SA72_M20G9lQ
同样的配置也可以使用环境变量:
$ docker run -d -p 8080:8080 -E COOKIE_SECURE=false -e LOGINSRV_JWT_SECRET=my_secret -e LOGINSRV_BACKEND=provider=simple,bob=secret tarent/loginsrv
API
GET /login
默认情况下,对于未认证请求返回简单的bootstrap风格登录表单,对于已认证请求返回用户信息页面。当调用接受JSON输出时,已认证请求返回token的JSON内容。
POST /login
执行登录并返回JWT。根据内容类型和参数,可以执行经典的JSON-Rest或重定向。
DELETE /login
删除JWT cookie。在web应用中也可以通过GET|POST /login?logout=true
调用。
JWT Token
根据提供者不同,token可能如下所示:
{
"sub": "smancke",
"picture": "https://avatars2.githubusercontent.com/u/4291379?v=3",
"name": "Sebastian Mancke",
"email": "s.mancke@tarent.de",
"origin": "github"
}
提供者后端
Htpasswd
针对htpasswd文件进行认证。支持MD5、SHA1和Bcrypt,但出于安全原因建议只使用Bcrypt。
示例:
loginsrv -htpasswd file=users
Simple
Simple是一个仅用于测试的演示提供者,它在内存中保存用户/密码表。
示例:
loginsrv -simple bob=secret
OAuth2
支持OAuth Web Flow(又称3-legged-OAuth flow)。当前支持以下OAuth提供者:
- GitHub
- Bitbucket
- Gitlab
OAuth提供者支持以下参数:
- client_id - OAuth Client ID
- client_secret - OAuth Client Secret
- scope - 空格分隔的范围列表(可选)
- redirect_uri - 替代重定向URI(可选)
GitHub启动示例:
$ docker run -p 80:80 tarent/loginsrv -github client_id=xxx,client_secret=yyy
自定义模板
可以通过template
参数提供自定义模板。模板使用Golang模板包。
最小化的无样式登录模板如下:
<!DOCTYPE html>
<html>
<head>
<!-- your styles -->
<head>
<body>
<!-- your header -->
{{ if .Error}}
<div class="alert alert-danger" role="alert">
<strong>Internal Error. </strong> Please try again later.
</div>
{{end}}
{{if .Authenticated}}
{{template "userInfo" . }}
{{else}}
{{template "login" . }}
{{end}}
<!-- your footer -->
</body>
</html>
自定义声明
可以通过提供包含用户数据的文件或提供声明的端点来自定义JWT令牌的内容。
用户文件
用户文件是一个YAML文件,包含将编码到令牌中的附加信息。成功通过后端系统认证后,将在文件中搜索用户,并使用claims参数的内容增强用户JWT声明参数。
示例:
- sub: bob
origin: htpasswd
claims:
role: superAdmin
- email: admin@example.org
origin: Google
claims:
role: admin
projects:
- example
- domain: example.org
origin: Google
claims:
role: user
projects:
- example
- groups:
- example/subgroup
- othergroup
origin: gitlab
claims:
role: admin
- claims:
role: unknown
用户端点
用户端点是一个http端点,提供已认证用户的附加信息。成功通过后端系统认证后,将调用端点并使用提供的信息增强用户JWT声明参数。
交互示例如下:
GET /claims?origin=google&sub=test@example.com&email=test@example.com HTTP/1.1
Host: localhost:8080
Accept: */*
Authorization: Bearer token
HTTP/1.1 200 OK
Content-Type: application/json
{
"sub":"test@example.com",
"uid":"113",
"origin":"google",
"permissions": ["read", "write"]
}
更多关于golang基于JWT的多后端认证登录微服务插件loginsrv的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang基于JWT的多后端认证登录微服务插件loginsrv的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang基于JWT的多后端认证登录微服务插件loginsrv使用指南
loginsrv是一个轻量级的登录微服务,支持多种后端认证方式并生成JWT令牌。下面我将详细介绍其使用方法和Golang示例代码。
1. loginsrv简介
loginsrv主要特性:
- 支持多种后端认证方式:htpasswd、OSIAM、HTTP基本认证、LDAP、OAuth2等
- 生成JWT令牌
- 轻量级,易于集成
- 支持CORS
- 可配置的JWT过期时间
2. 安装loginsrv
go get github.com/tarent/loginsrv
3. 基本使用示例
3.1 简单启动
loginsrv --jwt-secret mysecret --text-login
3.2 使用htpasswd后端
loginsrv --jwt-secret mysecret --htpasswd /path/to/users.htpasswd
4. Golang集成示例
4.1 直接调用loginsrv
package main
import (
"log"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("loginsrv",
"--jwt-secret", "mysecretkey",
"--backend", "provider=simple",
"--backend", "provider=htpasswd,file=users.htpasswd",
"--cookie-domain", "example.com",
"--cookie-name", "jwt_token",
"--host", "0.0.0.0",
"--port", "8080",
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
log.Println("Login service started on port 8080")
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
}
4.2 作为中间件使用
package main
import (
"net/http"
"os"
"github.com/tarent/loginsrv/login"
)
func main() {
config := login.DefaultConfig()
config.JwtSecret = "mysecretkey"
config.Backends = login.BackendOptions{
"simple": map[string]string{},
"htpasswd": map[string]string{
"file": "users.htpasswd",
},
}
config.Cookie.Domain = "example.com"
config.Cookie.Name = "jwt_token"
handler, err := login.NewHandler(config)
if err != nil {
panic(err)
}
http.Handle("/login", handler)
// 保护的路由示例
protected := http.NewServeMux()
protected.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Protected API"))
})
http.Handle("/api/", handler.Middleware(protected))
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
http.ListenAndServe(":"+port, nil)
}
5. JWT验证示例
package main
import (
"fmt"
"net/http"
"time"
"github.com/dgrijalva/jwt-go"
)
func verifyJWT(jwtToken, secret string) (bool, error) {
token, err := jwt.Parse(jwtToken, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte(secret), nil
})
if err != nil {
return false, err
}
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
fmt.Println("User:", claims["sub"])
fmt.Println("Expires:", time.Unix(int64(claims["exp"].(float64)), 0))
return true, nil
}
return false, nil
}
func protectedHandler(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie("jwt_token")
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
if valid, _ := verifyJWT(cookie.Value, "mysecretkey"); valid {
w.Write([]byte("Welcome to protected area!"))
} else {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
}
}
func main() {
http.HandleFunc("/protected", protectedHandler)
http.ListenAndServe(":8080", nil)
}
6. 多后端配置示例
loginsrv支持同时配置多个认证后端:
loginsrv \
--jwt-secret mysecret \
--backend provider=simple,bob=secret \
--backend provider=htpasswd,file=users.htpasswd \
--backend provider=ldap,host=ldap.example.com,base=dc=example,dc=com
7. 生产环境建议
- 使用强JWT密钥
- 启用HTTPS
- 设置合理的JWT过期时间
- 定期轮换JWT密钥
- 监控登录服务
8. 总结
loginsrv为Golang应用提供了简单易用的JWT认证解决方案,支持多种后端认证方式,可以轻松集成到现有系统中。通过中间件方式使用,可以方便地保护API路由。
以上示例展示了loginsrv的基本用法和Golang集成方式,您可以根据实际需求进行调整和扩展。