Iris 的基本认证中间件

科技   2024-11-23 07:51   广东  

概述

基本认证(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 应用程序提供了全面的解决方案。通过支持多种用户存储方法、提供密码加密和自定义错误处理等高级功能,以及易于集成,它是开发者的强大工具。


源自开发者
专注于提供关于Go语言的实用教程、案例分析、最新趋势,以及云原生技术的深度解析和实践经验分享。
 最新文章