CSRF(Cross-site request forgery)攻击是一种恶意攻击,它利用了用户的身份验证信息来执行未经授权的操作。它可以通过在受害者的浏览器中注入恶意代码来实施,这些代码会在受害者不知情的情况下向服务器发送请求。
CSRF 攻击防御主要是通过使用验证令牌来实现的。验证令牌是一个随机生成的字符串,由服务器生成并存储在会话中。当用户发送一个请求时,服务器会验证令牌是否正确,如果不正确则会拒绝请求。
// 在表单中加入隐藏字段 csrf_token <form action="..." method="post"> <input type="hidden" name="csrf_token" value="{{ csrf_token }}"> ... </form> // 在服务端校验 csrf_token 是否正确 if (request.method == 'POST') { if (request.POST['csrf_token'] != session['csrf_token']) { // 非法请求, 拒绝处理 return false; } else { // 处理正常的 POST 请求 } }
跨站请求伪造(英语:Cross-Site Request Forgery
),也被称为 one-click attack
或者 session riding
,通常缩写为 CSRF
或者 XSRF
, 是一种挟制用户在当前已登录的Web
应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS
)相比,XSS
利用的是用户对指定网站的信任,CSRF
利用的是网站对用户网页浏览器的信任。
这里我们选择通过token
的方式对请求进行校验,通过中间件的方式实现,CSRF
跨站点防御插件由社区包提供。
开发者可以通过对接口添加中间件的方式,增加token
校验功能。
感兴趣的朋友可以阅读插件源码 https://github.com/gogf/csrf
import "github.com/gogf/csrf"
csrf
插件支持自定义csrf.Config
配置,Config
中的Cookie.Name
是中间件设置到请求返回Cookie
中token
的名称,ExpireTime
是token
超时时间,TokenLength
是token
长度,TokenRequestKey
是后续请求需求带上的参数名。
s := g.Server()
s.Group("/api.v2", func(group *ghttp.RouterGroup) {
group.Middleware(csrf.NewWithCfg(csrf.Config{
Cookie: &http.Cookie{
Name: "_csrf",// token name in cookie
},
ExpireTime: time.Hour * 24,
TokenLength: 32,
TokenRequestKey: "X-Token",// use this key to read token in request param
}))
group.ALL("/csrf", func(r *ghttp.Request) {
r.Response.Writeln(r.Method + ": " + r.RequestURI)
})
})
通过配置后,前端在POST
请求前从Cookie
中读取_csrf
的值(即token
),然后请求发出时将token
以X-Token
(TokenRequestKey
所设置)参数名置入请求中(可以是Header
或者Form
)即可通过token
校验。
package main
import (
"net/http"
"time"
"github.com/gogf/csrf"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
// default cfg
func main() {
s := g.Server()
s.Group("/api.v2", func(group *ghttp.RouterGroup) {
group.Middleware(csrf.New())
group.ALL("/csrf", func(r *ghttp.Request) {
r.Response.Writeln(r.Method + ": " + r.RequestURI)
})
})
s.SetPort(8199)
s.Run()
}
package main
import (
"net/http"
"time"
"github.com/gogf/csrf"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
// set cfg
func main() {
s := g.Server()
s.Group("/api.v2", func(group *ghttp.RouterGroup) {
group.Middleware(csrf.NewWithCfg(csrf.Config{
Cookie: &http.Cookie{
Name: "_csrf",// token name in cookie
Secure: true,
SameSite: http.SameSiteNoneMode,// 自定义samesite
},
ExpireTime: time.Hour * 24,
TokenLength: 32,
TokenRequestKey: "X-Token",// use this key to read token in request param
}))
group.ALL("/csrf", func(r *ghttp.Request) {
r.Response.Writeln(r.Method + ": " + r.RequestURI)
})
})
s.SetPort(8199)
s.Run()
}
SameSite介绍参考文档https://web.dev/samesite-cookies-explained/https://web.dev/samesite-cookie-recipes/https://web.dev/s...
gudp模块也提供了一些常用的工具方法。使用方式:import "github.com/gogf/gf/v2/net/gudp"接口文档:https://pkg.go.dev/gi...
iris同样支持RESTful API,具体使用方法如下package mainimport "github.com/kataras/iris/v12"func main() {app := iris.Defaul...
要将请求正文绑定到类型,请使用模型绑定。iris目前支持JSON,JSONProtobuf,Protobuf,MsgPack,XML和YAML标准表单值(foo=barboo=ba...
我们首先创建一个存放模板文件的templates文件夹,然后在其内部写入一个index.html,代码如下!DOCTYPE htmlhtml lang="en"headme...
在Gin框架中记录日志方法如下package mainimport ("io""os""github.com/gin-gonic/gin")func main() {// 禁用控制台颜色,将日志...
你想优雅地重启或停止web服务器吗?有一些方法可以做到这一点。我们可以使用fvbock/endless来替换默认的ListenAndServer...
用于写入和读取非阻塞文件和套接字的实用程序类。主要有:BaseIOStream:用于读写的通用接口。IOStream:使用非阻塞套接...
修改源文件时自动重启服务器。大多数应用程序不应直接访问此模块。相反,将关键字参数autoreload=True传递给tornado.web.A...
警告这是一个比较高级的话题。如果您从FastAPI开始,您可能不需要这个。您可以声明额外的响应,包括额外的状态代码、媒体类型、...