概述
基本认证(Basic Authentication)中间件为保护你的 Iris Web 应用程序提供了一种强大而灵活的方法。它支持多种用户存储方式,包括内存列表、文件和数据库,并提供高级功能,如密码加密、自定义错误处理和会话过期。
安装
要在 Iris 应用中使用 basicauth
中间件,你需要导入它:
import "github.com/kataras/iris/v12/middleware/basicauth"
功能
认证函数
中间件的核心是 Allow
字段,这是一个具有以下签名的函数:
func(ctx iris.Context, username, password string) (any, bool)
此函数负责验证用户名和密码。它返回一个用户对象(或其他类型)和一个布尔值,指示认证是否成功。
用户结构(辅助)
虽然中间件不要求特定的用户结构,但你可以使用辅助结构来更方便地管理用户数据。以下是一个用户结构的示例:
type User struct {
Username string `json:"username"`
Password string `json:"password"`
Roles []string `json:"roles"`
}
内存中的用户存储
你可以使用用户结构的切片在内存中存储用户。这对于小型应用或测试目的非常有用。
var users = []User{
{"admin", "admin", []string{"admin"}},
{"kataras", "kataras_pass", []string{"manager", "author"}},
{"george", "george_pass", []string{"member"}},
{"john", "john_pass", []string{}},
}
基本设置
要设置中间件,创建一个 basicauth.Options
实例并将其传递给 basicauth.New
。
opts := basicauth.Options{
Realm: basicauth.DefaultRealm,
MaxAge: 10 * time.Minute,
GC: basicauth.GC{
Every: 2 * time.Hour,
},
Allow: basicauth.AllowUsers(users),
}
auth := basicauth.New(opts)
使用文件进行用户存储
你可以从文件(JSON 或 YAML)加载用户。这对于用户数据经常变化的应用程序非常有用。
auth := basicauth.Load("users.yml")
BCRYPT 选项
BCRYPT 选项允许你使用 bcrypt 进行密码哈希。Bcrypt 是一种设计为计算密集型的密码哈希函数,以抵抗暴力攻击。它被广泛用于安全存储密码。
auth := basicauth.Load("users.yml", basicauth.BCRYPT)
你也可以将 BCRYPT 选项与其他用户获取方法(如内存或数据库存储)结合使用。
使用数据库进行用户存储
为了更动态的用户管理,你可以通过数据库验证用户。以下是使用 MySQL 数据库设置中间件的示例:
package main
import (
"context"
"database/sql"
"fmt"
"os"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/basicauth"
_ "github.com/go-sql-driver/mysql"
)
type User struct {
ID int64 `db:"id" json:"id"`
Username string `db:"username" json:"username"`
Password string `db:"password" json:"password"`
Email string `db:"email" json:"email"`
}
func (u User) GetUsername() string {
return u.Username
}
func (u User) GetPassword() string {
return u.Password
}
func main() {
dsn := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?parseTime=true&charset=utf8mb4&collation=utf8mb4_unicode_ci",
getenv("MYSQL_USER", "user_myapp"),
getenv("MYSQL_PASSWORD", "dbpassword"),
getenv("MYSQL_HOST", "localhost"),
getenv("MYSQL_DATABASE", "myapp"),
)
db, err := connect(dsn)
if err != nil {
panic(err)
}
// Validate a user from database.
allowFunc := func(ctx iris.Context, username, password string) (any, bool) {
user, err := db.getUserByUsernameAndPassword(context.Background(), username, password)
return user, err == nil
}
opts := basicauth.Options{
Realm: basicauth.DefaultRealm,
ErrorHandler: basicauth.DefaultErrorHandler,
Allow: allowFunc,
}
auth := basicauth.New(opts)
app := iris.New()
app.Use(auth)
app.Get("/", index)
app.Listen(":8080")
}
func index(ctx iris.Context) {
user, _ := ctx.User().GetRaw()
// user is a type of main.User
ctx.JSON(user)
}
自定义错误处理
你可以通过设置 basicauth.Options
中的 ErrorHandler
字段来自定义错误处理行为。
opts := basicauth.Options{
ErrorHandler: func(ctx iris.Context, err error) {
ctx.StatusCode(iris.StatusUnauthorized)
ctx.JSON(iris.Map{"error": "Unauthorized"})
},
}
会话过期
中间件支持会话过期。你可以设置 MaxAge
字段来指定用户必须重新认证的时间。
opts := basicauth.Options{
MaxAge: 10 * time.Minute,
}
垃圾回收
要从内存中清除过期用户,你可以设置 GC
字段。
opts := basicauth.Options{
GC: basicauth.GC{
Every: 2 * time.Hour,
},
}
使用 BasicAuth 中间件测试处理程序
要测试使用 BasicAuth 中间件的处理程序,你可以使用 Iris 提供的 httptest
包。以下是如何测试处理程序的示例:
package main_test
import (
"testing"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/httptest"
"github.com/kataras/iris/v12/middleware/basicauth"
)
func TestIndexHandler(t *testing.T) {
opts := basicauth.Options{
Realm: basicauth.DefaultRealm,
Allow: basicauth.AllowUsers(users),
}
auth := basicauth.New(opts)
app := iris.New()
app.Use(auth)
app.Get("/", index)
e := httptest.New(t, app)
// Test with valid credentials
e.GET("/").WithBasicAuth("admin", "admin").Expect().Status(httptest.StatusOK).JSON().Object().Value("username").Equal("admin")
// Test with invalid credentials
e.GET("/").WithBasicAuth("admin", "wrongpassword").Expect().Status(httptest.StatusUnauthorized)
}
示例
以下是一个完整的示例,演示如何使用内存用户存储设置中间件:
package main
import (
"time"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/basicauth"
)
type User struct {
Username string `json:"username"`
Password string `json:"password"`
Roles []string `json:"roles"`
}
var users = []User{
{"admin", "admin", []string{"admin"}},
{"kataras", "kataras_pass", []string{"manager", "author"}},
{"george", "george_pass", []string{"member"}},
{"john", "john_pass", []string{}},
}
func main() {
opts := basicauth.Options{
Realm: basicauth.DefaultRealm,
MaxAge: 10 * time.Minute,
GC: basicauth.GC{
Every: 2 * time.Hour,
},
Allow: basicauth.AllowUsers(users),
}
auth := basicauth.New(opts)
app := iris.New()
app.Use(auth)
app.Get("/", index)
app.Listen(":8080")
}
func index(ctx iris.Context) {
user, _ := ctx.User().GetRaw()
ctx.JSON(user)
}
结论
基本认证中间件为保护你的 Iris Web 应用程序提供了全面的解决方案。通过支持多种用户存储方法、提供密码加密和自定义错误处理等高级功能,以及易于集成,它是开发者的强大工具。