WHCSRL 技术网

【Go开源宝藏】CORS 跨域 与 CSRF攻击 | 中间件

在这里插入图片描述

1. 什么是跨域

当一个请求url的协议域名端口三者之间任意一个与当前页面url不同即为跨域

当前页面url被请求页面url是否跨域原因
http://www.test.com/http://www.test.com/index.html同源(协议、域名、端口号相同)
http://www.test.com/https://www.test.com/index.html跨域协议不同(http/https)
http://www.test.com/http://www.baidu.com/跨域主域名不同(test/baidu)
http://www.test.com/http://blog.test.com/跨域子域名不同(www/blog)
http://www.test.com:8080/http://www.test.com:7001/跨域端口号不同(8080/7001)

因为域的不一致,与此同时由于安全问题,请求就会受到同源策略限制

通常,浏览器会对跨域请求作出限制。
浏览器之所以要对跨域请求作出限制,是出于安全方面的考虑,因为跨域请求有可能被不法分子利用来发动 CSRF攻击。

2. CSRF攻击

2.1 CSRF说明

CSRF(Cross-site request forgery)中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份在攻击页面对目标网站发起伪造用户操作的请求,达到攻击目的。

2.1 原理

​ CSRF 攻击的原理大致描述如下:

  1. 有两个网站,其中A网站是真实受信任的网站,而B网站是危险网站。
  2. 在用户登陆了受信任的A网站是,本地会存储A网站相关的Cookie,并且浏览器也维护这一个Session会话。
  3. 这时,如果用户在没有登出A网站的情况下访问危险网站B,那么危险网站B就可以模拟发出一个对A网站的请求(跨域请求)对A网站进行操作
  4. 而在A网站的角度来看是并不知道请求是由B网站发出来的(Session和Cookie均为A网站的),这时便成功发动一次 CSRF 攻击。

​ 因而 CSRF 攻击可以简单理解为:攻击者盗用了你的身份,以你的名义发送请求

CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。

3. CORS

3.1 简介

跨源资源共享 Cross-Origin Resource Sharing(CORS) 是一个新的 W3C 标准,它新增的一组HTTP首部字段,允许服务端其声明哪些源站有权限访问哪些资源。

换言之,它允许浏览器向声明了 CORS 的跨域服务器,发出 XMLHttpReuest 请求,从而克服 Ajax 只能同源使用的限制

简单介绍一下CORS中新增的 HTTP 首部字段

  • Access-Control-Allow-Origin
    响应首部中可以携带这个头部表示服务器允许哪些域可以访问该资源
c.Header("Access-Control-Allow-Origin", "*")        
  • 1
  • Access-Control-Allow-Methods
    预检请求的响应,指明实际请求所允许使用的HTTP方法
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")    
  • 1
  • Access-Control-Allow-Headers
    首部字段用于预检请求的响应,指明了实际请求中允许携带的首部字段
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma")
  • 1
  • Access-Control-Max-Age
    首部字段用于预检请求的响应,指定了预检请求能够被缓存多久。
c.Header("Access-Control-Max-Age", "172800")  
  • 1
  • Access-Control-Allow-Credentials
    首部字段用于预检请求的响应,指明实际请求所允许使用的HTTP方法。
c.Header("Access-Control-Allow-Credentials", "false")       
  • 1

3.2 引用

在中间件中设置编写即可!

func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method      	      //请求方法
		origin := c.Request.Header.Get("Origin")  //请求头部
		var headerKeys []string                   // 声明请求头keys
		for k := range c.Request.Header {
			headerKeys = append(headerKeys, k)
		}
		headerStr := strings.Join(headerKeys, ", ")
		if headerStr != "" {
			headerStr = fmt.Sprintf("access-control-allow-origin, access-control-allow-headers, %%%%s", headerStr)
		} else {
			headerStr = "access-control-allow-origin, access-control-allow-headers"
		}
		if origin != "" {
			c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
			c.Header("Access-Control-Allow-Origin", "*")        
			// 这是允许访问所有域
			c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")      
			//服务器支持的所有跨域请求的方法,为了避免浏览次请求的多次'预检'请求
			//  header的类型
			c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma")
			// 允许跨域设置,可以返回其他子段                                                                                                		 
			c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar")      
			// 跨域关键设置 让浏览器可以解析
			c.Header("Access-Control-Max-Age", "172800")        
			// 缓存请求信息 单位为秒
			c.Header("Access-Control-Allow-Credentials", "false")       
			//  跨域请求是否需要带cookie信息 默认设置为true
			c.Set("content-type", "application/json")      
			// 设置返回格式是json
		}
		//放行所有OPTIONS方法
		if method == "OPTIONS" {
			c.JSON(http.StatusOK, "Options Request!")
		}
		c.Next()        //  处理请求
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

配合gin框架使用

	r:=gin.Default()
	r.Use(middleware.Cors())
  • 1
  • 2

参考文献
1、https://www.jianshu.com/p/f880878c1398
2、https://blog.csdn.net/qq_38128179/article/details/84956552

小生凡一
微信公众号
获取源码 / 资料 / 联系博主
推荐阅读