gin框架中的会话控制
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的练习
模拟实现权限验证中间件
- 有2个路由,login和home
- login用于设置cookie
- home是访问查看信息的请求
- 在请求home之前,先跑中间件代码,检验是否存在cookie
访问home,会显示错误,因为权限校验未通过
然后访问登录的请求,登录并设置cookie
再次访问home,访问成功
- 认证中间件代码
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
}
}
- 处理请求函数
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"})
}
- 路由设置
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删除成功")
}
gin框架中的会话控制的更多相关文章
- 在gin框架中使用JWT
在gin框架中使用JWT JWT全称JSON Web Token是一种跨域认证解决方案,属于一个开放的标准,它规定了一种Token实现方式,目前多用于前后端分离项目和OAuth2.0业务场景下. 什么 ...
- golang gin框架中实现一个简单的不是特别精确的秒级限流器
起因 看了两篇关于golang中限流器的帖子: Gin 开发实践:如何实现限流中间件 常用限流策略--漏桶与令牌桶介绍 我照着用,居然没效果-- 时间有限没有深究.这实在是一个很简单的功能,我的需求是 ...
- gin框架中请求路由组的使用
1. gin框架中可以使用路由组来实现对路由的分类 package main import "github.com/gin-gonic/gin" func main() { rou ...
- gin框架中的路由
基本路由 gin框架中采用的路由库是基于httrouter做的 地址为:https://github.com/julienschmidt/httprouter httprouter路由库 点击查看代码 ...
- PHP中的会话控制
了解HTTP(超文本传输协议)可以知道,它采用请求与响应的模式,最大的特点就是无连接无状态. 无连接:每次连接仅处理一个客户端的请求,得到服务器响应后,连接就结束了 无状态:每个请求都是独立的,服务器 ...
- 理解PHP中的会话控制
会话控制是一种跟踪用户的通信方式,使用会话控制主要基于以下几点:由于http协议的无状态性,使得不能通过协议来建立两次请求之间的关联:对于通常的页面之间的数据传递方式get和post而言,主要处理参数 ...
- 【解决了一个小问题】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 ...
- golang gin框架中实现大文件的流式上传
一般来说,通过c.Request.FormFile()获取文件的时候,所有内容都全部读到了内存.如果是个巨大的文件,则可能内存会爆掉:且,有的时候我们需要一边上传一边处理. 以下的代码实现了大文件流式 ...
- gin框架中中间件的编写与使用
概念 一个完整的系统可能包括鉴权认证.权限管理.安全检查.日志记录等多维度的系统支持. 中间件位与服务器和实际业务处理程序之间,其含义就相当于在请求和具体的业务处理逻辑之间增加某些操作,这种以额外增加 ...
随机推荐
- 分布式NoSQL数据库MongoDB初体验-v5.0.5
概述 定义 MongoDB官网 https://www.mongodb.com/ 社区版最新版本5.0,其中5.2版本很快也要面世了 MongoDB GitHub源码 https://github.c ...
- ubuntu ffmpeg 转码错误
[aac @ 0xde2400] The encoder 'aac' is experimental but experimental codecs are not enabled, add '-st ...
- nim_duilib(16)之xml学习实战(GTAV加载窗口实现)
本文的目标 使用配置xml实现下面的结果 布局 整体采用水平布局,左边显示文字区域设置为垂直布局. lets go stage 1 创建一个空白窗体,并设置为半透明:同时,使得整个窗口可以移动,则 将 ...
- 【LeetCode】5083. Occurrences After Bigram 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字符串分割遍历 日期 题目地址:https://le ...
- 【LeetCode】563. Binary Tree Tilt 解题报告(Java & Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 Java解法 Python解法 日期 题目地址:ht ...
- 设置div背景透明的两种方法
实现div背景透明的两种方法 1.使用opacity属性 background-color:#000; opacity: 0.5; 这样做可以设置div内部所以区域的透明度,但是也会影响里面的文字,效 ...
- RabbitMQ,RocketMQ,Kafka 事务性,消息丢失和消息重复发送的处理策略
消息队列常见问题处理 分布式事务 什么是分布式事务 常见的分布式事务解决方案 基于 MQ 实现的分布式事务 本地消息表-最终一致性 MQ事务-最终一致性 RocketMQ中如何处理事务 Kafka中如 ...
- 简单学生管理系统HTML前端页面
效果图: 实现代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> ...
- ElasticSearch+Kibana安装部署
在安装ElasticSearch时遇到了很多坑,所以在这里做个笔记记录一下. 首先我考虑的是使用docker进行部署,结果发现虚拟机直接内存溢出,我也是无解了,也就是说使用docker部署还得注意容器 ...
- golang mongodb 驱动二次封装
mongodb 官方的go驱动包 go.mongodb.org/mongo-driver 使用起来比较繁琐,最近对其进行了二次封装 github地址:https://github.com/w3liu/ ...