Skip to main content

Request

Restful API

REST(Representational State Transfer),即表现层状态转化,Restful是用URL定位资源的HTTP标准风格。

  • Resource:资源(数据、文件、流等)。
  • Representational:资源的类型(JSON、MP4、PNG等)。
  • State Transfer:状态的变化(GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS)。
  • URI:Uniform Resource Identifier,统一资源标识符,泛指可以定位到某个资源的标识。
  • URL:Uniform Resource Locator,统一资源定位符,寻找资源的具体路径,如远程地址、HTTP网址、WS长连接地址等。

Restful API是使用Rest风格的API,遵循HTTP协议的一种接口设计风格。

GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS等方式是根据CRUD(Create、Read、Update、Delete)的行为来定义的一系列的HTTP动词。

Gin支持所有的HTTP请求方式,并有相应的参数处理方式。

// 获取数据 /info/1
r.GET()

// 创建数据
r.POST()

// 修改一组数组
r.PUT()

// 删除数据
r.DELETE()

// 打补丁 /info/age
r.PATCH()

// 获取(探测)请求头相关内容
r.HEAD()

// 常用于预检请求
// 主动发起一般会返回服务器支持的请求方法
r.OPTIONS()

复杂请求

在客户端发起请求,而实际客户端会自动先发起一次预检请求,到服务器验证是否有权限发起实际请求。如果有权限,则客户端发起实际的请求。如果没权限,则客户端会拦截服务器的响应。

  • 客户端在数据请求之前多一次OPTIONS请求(权限验证请求)。
  • 服务端会多一次响应(预响应)。
  • 预检请求只会在不同源的异步请求中出现(同源策略是针对异步请求的)。

对服务器数据的创建、更新、删除等操作,对服务器数据安全有重大影响,所以要进行一次预检请求。

预检请求

预检请求(Preflight Request)是浏览器在执行复杂跨源HTTP请求之前,自动发出的一个HTTP请求。这主要用于确保目标服务器支持跨源请求,并且服务器允许实际请求的方式和内容。

预检请求的请求方式通常为OPTIONS,一般不响应任何内容。

简单请求

  • 不是复杂的请求,都是简单请求。
  • 简单请求不会发起预检请求。
  • 简单请求只会出现在GET/POST/HEAD请求方式中。
  • 请求头:AcceptAccept-LanguageContent-LanguageContent-Type等。
  • Content-Typeapplication/x-www-form-urlencodedtext/plainmultiple/form-data

Web攻击

CSRF

CSRF(Cross-Site Request Forgery),即跨站请求伪造,是一种攻击方式,攻击者诱使用户在已认证的会话中执行不被用户意图的操作。攻击者利用用户的身份和权限,向目标网站发起恶意请求,这些请求是用户本身不知情的。

XSS

XSS(Cross-Site Scripting),即跨站脚本攻击,是一种常见的网络安全漏洞,攻击者通过在网页中注入恶意脚本,来窃取用户信息、篡改网页内容或执行其他恶意操作。

同源策略

同源策略是浏览器对于资源请求安全的一种策略,是对服务器更安全的一种做法。

协议、域名、端口三个必须一致才是同源,同源不会受到同源策略的影响,当不是同源时,会引起跨域问题。

跨域问题

跨域拦截的是服务器的响应,而不是客户端的请求,请求实际上已经发送出去。

package main

import (
"net/http"
"github.com/gin-gonic/gin"
)

func main() {
r := gin.Default()

r.GET("/user", func(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{
"code": 0,
"msg": "OK",
"data": map[string]any{
"id": 1,
"name": "JASON",
"age": 20,
},
})
})

r.Run()
}
/*
Access to fetch at 'http://localhost:8080/user' from origin 'http://127.0.0.1:5500'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
*/

如上,通过前端http://127.0.0.1:5500访问服务端http://localhost:8080/user时,因为同源策略被拦截了,因为在请求的资源中,并没有出现Access-Control-Allow-Origin的头信息。

Access-Control-Allow-Origin即访问控制许可源,如果响应头没有此信息,浏览器会认为服务器是不同意当前源访问的,因此会进行拦截。

解决跨域

Gin中可通过中间件的形式设置跨域:

var origins = []string{
"http://127.0.0.1:5500",
"http://localhost:5500",
}

func Cors() func(*gin.Context) {
return func(ctx *gin.Context) {

origin := ctx.GetHeader("Origin")

for _, o := range origins {
if o == origin {
ctx.Header("Access-Control-Allow-Origin", origin)
ctx.Header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,PATCH,HEAD")
ctx.Header("Access-Control-Allow-Headers", "Content-Type")

if ctx.Request.Method == "OPTIONS" {
ctx.JSON(http.StatusOK, "")
ctx.Abort()
return
}

ctx.Next()
}
}
}
}