1 Star 3 Fork 2

gin-ecosystem/gin-middleware

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
csrf.go 2.27 KB
一键复制 编辑 原始数据 按行查看 历史
aesoper 提交于 2020-05-20 15:06 . 添加日志中间件
/**
* @Author: aesoper
* @Description:
* @File: csrf
* @Version: 1.0.0
* @Date: 2020/5/19 19:26
*/
package gin_middleware
import (
"encoding/base64"
"gitee.com/aesoper/utils"
"gitee.com/gin-ecosystem/gin-middleware/consts"
"github.com/gin-gonic/gin"
"log"
"net/url"
"regexp"
"strings"
)
type CSRFConfig struct {
Skipper Skipper
QueryAllowHosts func() []string
QueryAllowPattern func() []string
Validator func(c *gin.Context) bool
}
const defaultCsrfSecret = "11111111111111111"
// 默认算法token生成算法为 secret + "-" + 时间戳 + "-" + 8位随机数
func DefaultTokenValidator(c *gin.Context) bool {
token := c.Request.Header.Get(consts.HeaderXCSRFToken)
if token == "" {
return false
}
if str, err := base64.StdEncoding.DecodeString(token); err != nil {
return false
} else {
tokenStr := string(str)
arr := strings.Split(tokenStr, "-")
if len(arr) != 3 || arr[0] != defaultCsrfSecret || len(arr[2]) != 8 {
return false
}
// TODO 后续可以添加时间验证
}
return true
}
func NewCSRF(c CSRFConfig) gin.HandlerFunc {
if c.Skipper == nil {
c.Skipper = DefaultSkipper
}
var validations []func(*url.URL) bool
if c.QueryAllowHosts != nil {
for _, r := range c.QueryAllowHosts() {
validations = append(validations, utils.MatchHostSuffix(r))
}
}
if c.QueryAllowPattern != nil {
for _, p := range c.QueryAllowPattern() {
validations = append(validations, utils.MatchPattern(regexp.MustCompile(p)))
}
}
return func(ctx *gin.Context) {
if c.Skipper(ctx) {
ctx.Next()
return
}
referer := ctx.Request.Header.Get("Referer")
if referer == "" {
log.Println("The request's Referer or Origin header is empty.")
ctx.AbortWithStatus(403)
return
}
illegal := true
if uri, err := url.Parse(referer); err == nil && uri.Host != "" {
for _, validate := range validations {
if validate(uri) {
illegal = false
break
}
}
}
if illegal {
log.Printf("The request's Referer header `%s` does not match any of allowed referers.\n", referer)
ctx.AbortWithStatus(403)
return
}
// 添加隐藏csrf-token的认证
if c.Validator != nil {
if !c.Validator(ctx) {
log.Println("the X-CSRF-Token is invalid.")
ctx.AbortWithStatus(403)
return
}
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/gin-ecosystem/gin-middleware.git
git@gitee.com:gin-ecosystem/gin-middleware.git
gin-ecosystem
gin-middleware
gin-middleware
master

搜索帮助