栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

Beego2 使用Session时SetCookie无效

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Beego2 使用Session时SetCookie无效

Beego2已经发布有一段时间了,之前项目都是使用JWT做会话管理,一直没用Session,本次发文记录一下使用的坑。

  1. 如何安装Beego
	go get github.com/beego/beego/v2@v2.0.0
  1. 如何在项目中引用Beego2?
	package main
	import "github.com/beego/beego/v2/server/web"
	//在Beego2中,默认包名为web,在Beego1中,默认包名为Beego
	func main() {
	    //启动Beego
	     web.Run()
	}
  1. Beego2的Session模块,传送门:Session模块
    开启Session的两种方式:在web.run()启用Session
	package main
	import "github.com/beego/beego/v2/server/web"
	func main() {
		//设置Session启用
		 web.BConfig.WebConfig.Session.SessionOn = true
	    //启动Beego
	     web.Run()
	}
	

第二种方式:通过配置文件修改

	//启用Session
	sessionon=true
	//设置Session别名,这里影响Set-Cookie是key的名字替换为SessionName
	SessionName="SessionName"

由于Chrome的安全策略限制,使用Beego2的Session中,初次登入调用Set-Cookie时,Chrome无法将用户凭据保存在本地Cookie中,原因是Chrome默认将SameSite设置为Lax,导致跨域时无法携带和保存Cookie。

解决方法可以手动设置Cookie,并设置SameSite属性,并在前端框架中配置允许用户使用Https访问页面。

实例代码如下:

	package controllers
	
	import (
		"context"
		"net/http"
	)
	//获取生成Session的ID
	sid := c.CruSession.SessionID(context.Background())
	http.SetCookie(c.Ctx.ResponseWriter, &http.Cookie{
		Name:     "SessionNmae",
		Value:    sid,
		Path:     "/",
		//为Cookie设置Secure属性
		Secure:   true,
		//设置HttpOnly属性为True,那么通过JS脚本将无法读取到cookie信息
		HttpOnly: true,
		//显示设置SameSite为None
		SameSite: http.SameSiteNoneMode, 
		//设置Cookie过期时间
		Expires:  time.Now().Add(8 * time.Hour),
	})

设置完成后在调用Login接口,你会发现Chrome中的Cookie可以正常保存到本地了。

方案2:
  1. 当在Config文件中Session = on时,使用默认配置会导致Beego2进行AutoSetCookie
// 文件路径 : /beego/server/web/config.go
func newBConfig() *Config {
	res := &Config{
		..... //省略一部分代码
		WebConfig: WebConfig{
			....
			Session: SessionConfig{
				SessionOn:                    false,
				SessionProvider:              "memory",
				SessionName:                  "beegosessionID",
				SessionGCMaxLifetime:         3600,
				SessionProviderConfig:        "",
				SessionDisableHTTPOnly:       false,
				SessionCookieLifeTime:        0, 
				// set cookie default is the browser life
                //重点在这里,AutoSetCookie会自动给没有Cookie的请求返回一个新的Cookie,Cookie=SessionID
				SessionAutoSetCookie:         true,
				SessionDomain:                "",
				SessionEnableSidInHTTPHeader: false, 
				SessionNameInHTTPHeader:      "Beegosessionid",
				SessionEnableSidInURLQuery:   false, 
				SessionCookieSameSite:        http.SameSiteDefaultMode,
			},
		},
    ...... //省略一部分代码
	}
	res.RecoverFunc = defaultRecoverPanic
	return res
}
  1. 关闭AutoSetCookie,只需要在Config文件中设置
	SessionAutoSetCookie = false
  1. 之前我们是这么处理的
	
	sid := c.CruSession.SessionID(context.Background())
		http.SetCookie(c.Ctx.ResponseWriter, &http.Cookie{
		Name:     "SID",
		Value:    sid,
		Path:     "/",
		Secure:   true,
		HttpOnly: true,
		SameSite: http.SameSiteNoneMode,
		Expires:  time.Now().Add(8 * time.Hour),
	})
  1. 这样有个缺点,就是Header会产生两个Set-Cookie字段,可以使用以下方案避免
	func (c *AccountController) Login() {
	  if (登录验证通过){
			  doFunctionB();
	  }else {
	    doFunctionA();
	  }
	  //一个参数Cookie名字,第二个参数Cookie值,第三个参数是不定值,分别用来设置Path, Domain【Domain必须为空,否则无法SetCookie无法保存到本地】, Secure, HttpOnly,SameSite
	  c.Ctx.Output.Cookie("SID", sid, 8*time.Hour, "/", "", true, true,"None")
	}
  1. Beego2调用AutoSetCookie底层调用的设置Cookie的源码,可供读者参考,在BeegoV2.0.2新增SameSite字段,V2.0.1及以下版本无法设置SameSite
	func (output *BeegoOutput) Cookie(name string, value string, others ...interface{}) {
		var b bytes.Buffer
		fmt.Fprintf(&b, "%s=%s", sanitizeName(name), sanitizeValue(value))
	
		// fix cookie not work in IE
		if len(others) > 0 {
			var maxAge int64
	
			switch v := others[0].(type) {
			case int:
				maxAge = int64(v)
			case int32:
				maxAge = int64(v)
			case int64:
				maxAge = v
			}
	
			switch {
			case maxAge > 0:
				fmt.Fprintf(&b, "; Expires=%s; Max-Age=%d", time.Now().Add(time.Duration(maxAge)*time.Second).UTC().Format(time.RFC1123), maxAge)
			case maxAge < 0:
				fmt.Fprintf(&b, "; Max-Age=0")
			}
		}
	
		// the settings below
		// Path, Domain, Secure, HttpOnly
		// can use nil skip set
	
		// default "/"
		tmpPath := "/"
		if len(others) > 1 {
			if v, ok := others[1].(string); ok && len(v) > 0 {
				tmpPath = sanitizeValue(v)
			}
		}
		fmt.Fprintf(&b, "; Path=%s", tmpPath)
	
		// default empty
		if len(others) > 2 {
			if v, ok := others[2].(string); ok && len(v) > 0 {
				fmt.Fprintf(&b, "; Domain=%s", sanitizeValue(v))
			}
		}
	
		// default empty
		if len(others) > 3 {
			var secure bool
			switch v := others[3].(type) {
			case bool:
				secure = v
			default:
				if others[3] != nil {
					secure = true
				}
			}
			if secure {
				fmt.Fprintf(&b, "; Secure")
			}
		}
	
		// default false. for session cookie default true
		if len(others) > 4 {
			if v, ok := others[4].(bool); ok && v {
				fmt.Fprintf(&b, "; HttpOnly")
			}
		}
	
		// default empty
		if len(others) > 5 {
			if v, ok := others[5].(string); ok && len(v) > 0 {
				fmt.Fprintf(&b, "; SameSite=%s", sanitizeValue(v))
			}
		}
	
		output.Context.ResponseWriter.Header().Add("Set-Cookie", b.String())
	}

可以看到Cookie的设置成功了,Chrome也不会出现SameSite的Warning

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/990262.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号