Go使用cookie做用户登录管理

本篇主要讲解如何在Go中使用cookie做用户登录验证

cookie与token的区别

  1. token和cookie一样都是首次登陆时,由服务器下发,都是当交互时进行验证的功能,作用都是为无状态的HTTP提供的持久机制。
  2. token存在哪儿都行,localstorage或者cookie。
  3. cookie:服务员看你的身份证,给你一个编号,以后,进行任何操作,都出示编号后服务员去看查你是谁。
  4. token:直接给服务员看自己身份证
  5. token优势在于,token由于服务器端不存储会话,所以可扩展性强,token还可用于APP中。

使用cookie做登录验证

1. 生成一个自定义的cookie值

我这里使用的是用户id加时间戳的方式是生成一个不重复唯一的cookie值

func CreateCookie(userid uint) (cookieValue string, err error) {
   //获取到当前时间戳,以秒为单位
   timeunix := time.Now().Unix()
   //cookie的过期时间
   timeunix = timeunix + (24 * 7 * 3600)
   var str = strconv.Itoa(int(userid)) + ":" + strconv.Itoa(int(timeunix))
   key := []byte("2fa6c1e9")
   //使用DES加密算法进行加密
   strEncrypted, err := Encrypt(str, key)
   if err != nil {
   	log.Fatal(err)
   }
   cookieValue = strEncrypted
   return cookieValue, err

}

这里使用的是Go的DES对称加密是算法生成cookie

DES加密算法

DES是一种对称加密算法,又称为美国数据加密标准。DES加密时以64位分组对数据进行加密,加密和解密都使用的是同一个长度为64位的密钥,实际上只用到了其中的56位,密钥中的第8、16…64位用来作奇偶校验。DES有ECB(电子密码本)和CBC(加密块)等加密模式。
DES算法的安全性很高,目前除了穷举搜索破解外, 尚无更好的的办法来破解。其密钥长度越长,破解难度就越大。
填充和去填充函数。
下面是DES算法的使用

//解密
func Decrypt(decrypted string, key []byte) (string, error) {
	src, err := hex.DecodeString(decrypted)
	if err != nil {
		return "", err
	}
	block, err := des.NewCipher(key)
	if err != nil {
		return "", err
	}
	out := make([]byte, len(src))
	dst := out
	bs := block.BlockSize()
	if len(src)%bs != 0 {
		return "", errors.New("crypto/cipher: input not full blocks")
	}
	for len(src) > 0 {
		block.Decrypt(dst, src[:bs])
		src = src[bs:]
		dst = dst[bs:]
	}
	out = ZeroUnPadding(out)
	return string(out), nil
}

//加密
func Encrypt(text string, key []byte) (string, error) {
	src := []byte(text)
	block, err := des.NewCipher(key)
	if err != nil {
		return "", err
	}
	bs := block.BlockSize()
	src = ZeroPadding(src, bs)
	if len(src)%bs != 0 {
		return "", errors.New("Need a multiple of the blocksize")
	}
	out := make([]byte, len(src))
	dst := out
	for len(src) > 0 {
		block.Encrypt(dst, src[:bs])
		src = src[bs:]
		dst = dst[bs:]
	}
	return hex.EncodeToString(out), nil
}

func ZeroPadding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{0}, padding)
	return append(ciphertext, padtext...)
}

func ZeroUnPadding(origData []byte) []byte {
	return bytes.TrimFunc(origData,
		func(r rune) bool {
			return r == rune(0)
		})
}

2.Go使用cookie

在生成一个唯一的cookie值后,使用Go将这一个唯一的cookie值存入浏览器的cookie中

c.SetCookie("abc", "123", 24*7*3600, "/", "localhost:8081", false, true)

里面的参数
参数1:name,设置cookie的key
参数2:value,设置cookie的值
参数3:maxAge:设置cookie有效期
参数4:path:设置cookie的路径,一般设置根目录/代表当前域名下的所有页面都可以获取该cookie,例如设置为/users代表在/users这个路由下才可以访问这个cookie,像/article文章路由下的页面则无法访问这个cookie
参数5:domain:设置cookie域名,如下我设置域名为.go.com代表以.go.com为域名或者go.com的二级域名都可以访问这个cookie,像java.com这种域名就无法访问这个cookie,localhost也不可以访问这个cookie
参数6:secure,设置为true的时候只有https才可以访问,http不可以访问
参数7:httpOnly,此项为微软对cookie做的扩展,如果设置了httpOnly,则通过程序(js、applet等等)将无法读取到cookie的信息,防止XSS攻击

应用中间件

func SessionAuthMiddleware() func(c *gin.Context) {
	return func(c *gin.Context) {
		// 获取客户端cookie并校验
		//拿到请求头中的cookie
		cookie := c.Request.Header.Get("Cookie")
		//切分拿到的cookie
		parts := strings.SplitN(cookie, "=", 2)
		fmt.Println("cookie", parts[1])
		//取出redis中对应的cookie
		redisCookie, err := redis.GetRedisCookie(parts[1])
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"msg": "查询失败"})
			return
		}
		if len(cookie) != 0 {
			if parts[1] == redisCookie {
				c.Next()
				return
			}
		}
		// 返回错误
		c.JSON(http.StatusUnauthorized, gin.H{"msg": "用户未登录"})
		// 若验证不通过,不再调用后续的函数处理
		c.Abort()
		return
	}

}

中间件的应用
在这里插入图片描述
之后就可以检测用户是否已经登录,并在浏览器中保存了一个带有用户信息并加密的可解析的cookie。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值