- 实现原理
- 代码实现
- 自建基础认证中间件
- 优化点
1.实现原理
BasicAuth是一种浏览器端实现的简单认证方式,在请求Headers中检查Authorization字段,是否存在,并且在有效期内,如果不满足条件。返回401 Unauthorised ,浏览器端弹窗输入用户名密码。
步骤1. 客户端请求
步骤2. 服务端验证是否包含字段Authorization
步骤3.服务端验证,包含Authorization,验证为空,验证用户密码是否和服务端信息一致
步骤4.返回信息,验证通过直接返回,不通过返回
code 401
header:WWW-Authenticate:Basic realm=access info
2. 代码实现
package main
import (
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/basicauth"
"time"
)
func newApp() *iris.Application {
app := iris.New()
// 配置信息 users{username:password} 可配置多个
basicAuthConfig := basicauth.Config{
Users: map[string]string{"admin":"admin"},
Expires: time.Duration(30) * time.Minute,
}
authentication := basicauth.New(basicAuthConfig)
authRouter := app.Party("/",authentication)
authRouter.Get("/ping", func(ctx iris.Context) {
ctx.WriteString("pong")
})
authRouter.Get("/profile", h)
return app
}
func main() {
app := newApp()
app.Run(iris.Addr(":8080"))
}
func h(ctx iris.Context) {
username,password,ok :=ctx.Request().BasicAuth()
if ok {
ctx.JSON(iris.Map{
"username":username,
"password": password,
})
}
}
3. 自建基础认证中间件
package basicauth
import (
"encoding/base64"
"fmt"
"github.com/kataras/iris/v12/context"
"strings"
)
//type BasicAuthMiddleware context.Handler
type BasicAuthConfig struct {
Users map[string]string
Realme string
}
// todo func DefaultConfig
// todo 配置信息 绑定到basicauth上
// todo 过期时间
func NewBasicAuth(config BasicAuthConfig) context.Handler {
return func(ctx context.Context) {
//查看Authorization是否存在
Authorization := ctx.GetHeader("Authorization")
Authorization = strings.TrimPrefix(Authorization, "Basic ")
if Authorization == "" {
NoAuth(ctx, config.Realme)
ctx.StopExecution()
return
}
//解析Authorization
res := parseAuthorization(Authorization, config.Users)
if !res {
NoAuth(ctx, config.Realme)
ctx.StopExecution()
return
}
ctx.Next()
}
}
func parseAuthorization(Authorization string, users map[string]string) bool {
userinfo, err := base64.StdEncoding.DecodeString(Authorization)
if err != nil {
return false
}
fmt.Println(string(userinfo))
user := strings.Split(string(userinfo), ":")
name := user[0]
password := user[1]
if pass, ok := users[name]; ok && pass == password {
return true
}
return false
}
func NoAuth(ctx context.Context, realm string) {
ctx.StatusCode(401)
if realm == "" {
ctx.Header("WWW-Authenticate", "Basic realm=access App")
} else {
ctx.Header("WWW-Authenticate", "Basic realm="+realm)
}
}
4. 代码优化点
- 配置信息,创建默认配置方法,调用时先使用默认配置,然后根据传递的配置信息,再修改
- 定义basicauth结构体,汇总信息
网友评论