Cookie介绍

  • Http协议是无状态的,服务器不能记录浏览器的访问状态,也就是说服务器不能判断请求的客户端是否已经登录
  • Cookie就是解决http协议无状态的方案之一
  • Cookie实际上就是服务器保存在浏览器上的一小段文本信息,浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求
  • Cookie由服务器创建,并发送给浏览器,最终由浏览器进行保存

cookie的用途:

测试服务端发送cookie给客户端,客户端请求时携带cookie

Cookie的使用

测试服务端发送cookie给客户端,客户端请求时携带cookie

func someCookie(context *gin.Context) {
cookie, err := context.Cookie("key_cookie")
if err != nil {
// 给客户端设置cookie
context.SetCookie(
"key_cookie",
"value_cookie",
60, // maxAge int, 单位为秒
"/", // path,cookie所在目录
"127.0.0.1", // domain string,域名
false, // secure 是否智能通过https访问
false, // httpOnly bool 是否允许别人通过js获取自己的cookie
)
}
fmt.Println("cookie的值是:", cookie)
}

Cookie的练习

  • 模拟实现权限验证中间件

    1. 有2个路由,login和home
    2. login用于设置cookie
    3. home是访问查看信息的请求
    4. 在请求home之前,先跑中间件代码,检验是否存在cookie
  • 访问home,会显示错误,因为权限校验未通过

  • 然后访问登录的请求,登录并设置cookie

  • 再次访问home,访问成功

  1. 认证中间件代码
func AuthMiddleware() gin.HandlerFunc {
return func(context *gin.Context) {
// 获取客户端cookie并校验
if cookie, err := context.Cookie("username"); err == nil {
if cookie == "mayanan" {
context.Next()
return
}
}
// 返回错误
context.JSON(http.StatusUnauthorized, gin.H{"data": "认证失败"})
// 若认证失败,不用调用后续的函数处理
context.Abort()
return
}
}
  1. 处理请求函数
func someLogin(context *gin.Context) {
context.SetCookie(
"username",
"mayanan",
60, // maxAge int, 单位为秒
"/", // path,cookie所在目录
"127.0.0.1", // domain string,域名
false, // secure 是否智能通过https访问
false, // httpOnly bool 是否允许别人通过js获取自己的cookie
)
context.JSON(200, "登录成功")
}
func someHome(context *gin.Context) {
context.JSON(200, gin.H{"data": "home"})
}
  1. 路由设置
router.GET("/some-login", someLogin)
router.GET("/some-home", middleware.AuthMiddleware(), someHome)

Cookie的缺点

  • 不安全,明文
  • 增加带宽消耗
  • 可以被禁用
  • cookie有上限

Sessions

gorilla/sessions为自定义session后端提供cookie和文件系统session以及基础结构。

github链接

主要功能是:

简单的API:将其用作设置签名(以及可选的加密)cookie的简便方法。

内置的后端可将session存储在cookie或文件系统中。

Flash消息:一直持续读取的session值。

切换session持久性(又称“记住我”)和设置其他属性的便捷方法。

旋转身份验证和加密密钥的机制。

每个请求有多个session,即使使用不同的后端也是如此。

自定义session后端的接口和基础结构:可以使用通用API检索并批量保存来自不同商店的session。

基于session实现上面的练习

  • session-login session-home
func sessionLogin(context *gin.Context) {
// 初始化一个cookie存储对象
// mayanan.cn是一个自己的秘钥
var store = sessions.NewCookieStore([]byte("mayanan.cn"))
// 获取一个session对象,session-name是session的名字
session, err := store.Get(context.Request, "session-name")
if err != nil {
fmt.Println(err)
return
}
// 在session中存储值
session.Values["foo"] = "bar"
session.Values[42] = 43
// 保存更改 session默认过期时间:一个月
session.Save(context.Request, context.Writer)
context.JSON(http.StatusOK, "登录成功")
}
func sessionHome(context *gin.Context) {
context.JSON(200, gin.H{"data": "sessionHome"})
}
  • 中间件获取session,如果解析失败,拦截请求
func AuthMiddlewareSession() gin.HandlerFunc {
var store = sessions.NewCookieStore([]byte("mayanan.cn"))
return func(context *gin.Context) {
session, err := store.Get(context.Request, "session-name")
if err != nil {
context.JSON(http.StatusUnauthorized, gin.H{"err": err})
context.Abort() // 结束后续的请求处理
return
}
fooInfo := session.Values["foo"]
age := session.Values[42]
if fooInfo == "bar" && age == 43 {
context.Next()
return
}
context.JSON(http.StatusUnauthorized, gin.H{
"err": "身份认证失败",
})
context.Abort()
return
}
}
  • 路由配置
router.GET("/session-login", sessionLogin)
router.GET("/session-home", middleware.AuthMiddlewareSession(), sessionHome)
  • 删除session值

    将session的最大存储时间设置为小于零的数即为删除
session.Options.MaxAge = -1
session.Save(r, w)

案例:

func sessionDelete(context *gin.Context) {
story := sessions.NewCookieStore([]byte("mayanan.cn"))
session, err := story.Get(context.Request, "session-name")
if err != nil {
context.JSON(http.StatusUnauthorized, err.Error())
context.Abort()
return
}
session.Options.MaxAge = -1
session.Save(context.Request, context.Writer)
context.String(200, "session删除成功")
}
  • session默认存储到了签名的cookie中了
  • 如果想存储到mysql中:github链接
  • 存储到redis中:github链接

gin框架中的会话控制的更多相关文章

  1. 在gin框架中使用JWT

    在gin框架中使用JWT JWT全称JSON Web Token是一种跨域认证解决方案,属于一个开放的标准,它规定了一种Token实现方式,目前多用于前后端分离项目和OAuth2.0业务场景下. 什么 ...

  2. golang gin框架中实现一个简单的不是特别精确的秒级限流器

    起因 看了两篇关于golang中限流器的帖子: Gin 开发实践:如何实现限流中间件 常用限流策略--漏桶与令牌桶介绍 我照着用,居然没效果-- 时间有限没有深究.这实在是一个很简单的功能,我的需求是 ...

  3. gin框架中请求路由组的使用

    1. gin框架中可以使用路由组来实现对路由的分类 package main import "github.com/gin-gonic/gin" func main() { rou ...

  4. gin框架中的路由

    基本路由 gin框架中采用的路由库是基于httrouter做的 地址为:https://github.com/julienschmidt/httprouter httprouter路由库 点击查看代码 ...

  5. PHP中的会话控制

    了解HTTP(超文本传输协议)可以知道,它采用请求与响应的模式,最大的特点就是无连接无状态. 无连接:每次连接仅处理一个客户端的请求,得到服务器响应后,连接就结束了 无状态:每个请求都是独立的,服务器 ...

  6. 理解PHP中的会话控制

    会话控制是一种跟踪用户的通信方式,使用会话控制主要基于以下几点:由于http协议的无状态性,使得不能通过协议来建立两次请求之间的关联:对于通常的页面之间的数据传递方式get和post而言,主要处理参数 ...

  7. 【解决了一个小问题】gin框架中出现如下错误:"[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 500"

    POST到数据到一条gin框架的接口后,客户端收到400错误,并且返回了业务中返回的"decode json fail". 关键代码是: func report(c *gin.Co ...

  8. golang gin框架中实现大文件的流式上传

    一般来说,通过c.Request.FormFile()获取文件的时候,所有内容都全部读到了内存.如果是个巨大的文件,则可能内存会爆掉:且,有的时候我们需要一边上传一边处理. 以下的代码实现了大文件流式 ...

  9. gin框架中中间件的编写与使用

    概念 一个完整的系统可能包括鉴权认证.权限管理.安全检查.日志记录等多维度的系统支持. 中间件位与服务器和实际业务处理程序之间,其含义就相当于在请求和具体的业务处理逻辑之间增加某些操作,这种以额外增加 ...

随机推荐

  1. ACwing1208. 翻硬币

    题目: 小明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情形是:**oo***oooo 如果 ...

  2. SpringBoot使用Aspect切面拦截打印请求参数

    引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sp ...

  3. Xshell连接Ubuntu服务器连接不上 显示拒绝了密码

    确保下方两个都安装了 sudo apt-get install openssh-server sudo apt-get install ssh 修改 vim /etc/ssh/sshd_config ...

  4. 【LeetCode】 202. Happy Number 解题报告(Java & Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 迭代 日期 [LeetCode] 题目地址:h ...

  5. Glossary Collection

    目录 直接修饰用 间接强调用 (多为副词) 过渡用 特别的名词 动词 词组 各种介词 句子 摘要 引言 总结 正文 实验 直接修饰用 Word 含义 例句 近义词 nuanced adj. 微妙的:具 ...

  6. uniapp中使用animate.css4.1.1动画库在小程序中不生效解决办法

    找到源码animate.css修改以下代码 :root { --animate-duration: 1s; --animate-delay: 1s; --animate-repeat: 1; } // ...

  7. MySQL数据库报错 > 1366 - Incorrect string value: ‘\xE6\xB1\x9F\xE6\x96\x87‘ for column ‘Teacher‘ at row 1

    数据库报错这个多半是数据库在创建的时候没有选择字符编码,导致输入中文的时候出现报错. > 1366 - Incorrect string value: '\xE6\xB1\x9F\xE6\x96 ...

  8. Java Web程序设计笔记 • 【第4章 JavaBean和JSP标准动作】

    全部章节   >>>> 本章目录 4.1 JavaBean 4.1.1 JavaBean 概述 4.1.2 JavaBean的重要性 4.1.3 JavaBean的特点 4.1 ...

  9. Android开发 PorgressBar(进度条)的使用

    圆环进度条(默认)和水平进度条: <?xml version="1.0" encoding="utf-8"?> <LinearLayout x ...

  10. HAproxy开启日志记录

    1.说明 HAproxy在默认情况不会记录日志, 不仅要在haproxy.conf中配置日志输出, 还需要修改系统日志的配置文件. 2.修改haproxy.conf 在haproxy.conf文件中增 ...