Cookie/Session

Posted yzg-14

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cookie/Session相关的知识,希望对你有一定的参考价值。

1. Cookie

  • HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出
  • Cookie就是解决HTTP协议无状态的方案之一,中文是小甜饼的意思
  • Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求
  • Cookie由服务器创建,并发送给浏览器,最终由浏览器保存

2. Cookie的用途

  • 保持用户登录状态
  • 京东购物车

3. cookie的使用

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

import (
	"github.com/gin-gonic/gin"
	"fmt"
)

func main() {
	// 创建路由
	r := gin.Default()
	// 服务端要给客户端cookie
	r.GET("cookie", func(c *gin.Context) {
		// 获取客户端是否携带cookie
		cookie, err := c.Cookie("key_cookie") //c.Request.Cookie也行
		if err != nil {
			cookie = "NotSet"
			// 给客户端设置cookie
				// maxAge 单位为秒
				// path cookie所在目录
				// domain 域名 
				// secure 是否智能通过https访问
				// httpOnly 是否允许别人通过js获取自己的cookie
			c.SetCookie("key_cookie", "value_cookie", 60, "/",
				"localhost", false, true)
		}
		fmt.Printf("cookie的值是: %s
", cookie)
	})
	r.Run(":8000")
}

技术图片

3.1 使用

package main

import (
   "github.com/gin-gonic/gin"
   "net/http"
)

func AuthMiddleWare() gin.HandlerFunc {
   return func(c *gin.Context) {
      // 获取客户端cookie并校验
      if cookie, err := c.Cookie("abc"); err == nil {
         if cookie == "123" {
            c.Next()
            return
         }
      }
      // 返回错误
      c.JSON(http.StatusUnauthorized, gin.H{"error": "err"})
      // 若验证不通过,不再调用后续的函数处理
      c.Abort()
      return
   }
}

func main() {
   // 创建路由
   r := gin.Default()
   r.GET("/login", func(c *gin.Context) {
      // 设置cookie
      c.SetCookie("abc", "123", 60, "/",
         "localhost", false, true)
      // 返回信息
      c.String(200, "Login success!")
   })
   r.GET("/home", AuthMiddleWare(), func(c *gin.Context) {
      c.JSON(200, gin.H{"data": "home"})
   })
   r.Run(":8000")
}

3.2 Cookie的缺点

  • 不安全,明文

  • 增加带宽消耗

  • 可以被禁用

  • cookie有上限

4. Session

  • Session可以弥补Cookie的不足,Session必须依赖于Cookie才能使用,生成一个SessionId放在Cookie里传给客户端就可以

技术图片

技术图片

4.1 session中间件

技术图片

session.go

package session

type Session interface {
   Set(key string, value interface{}) error
   Get(key string) (interface{}, error)
   Del(key string) error
   Save() error
}

session_mgr.go

package session

// 定义管理者,管理所有session
type SessionMgr interface {
   // 初始化
   Init(addr string, options ...string) (err error)
   CreateSession() (session Session, err error)
   Get(sessionId string) (session Session, err error)
}

memory.go

package session

import (
   "sync"
   "errors"
)

// 对象
//    MemorySeesion设计:
//    定义MemorySeesion对象(字段:sessionId、存kv的map,读写锁)
//    构造函数,为了获取对象
//    Set()
//    Get()
//    Del()
//    Save()

type MemorySession struct {
   sessionId string
   // 存kv
   data   map[string]interface{}
   rwlock sync.RWMutex
}

// 构造函数
func NewMemorySession(id string) *MemorySession {
   s := &MemorySession{
      sessionId: id,
      data:      make(map[string]interface{}, 16),
   }
   return s
}

func (m *MemorySession) Set(key string, value interface{}) (err error) {
   // 加锁
   m.rwlock.Lock()
   defer m.rwlock.Unlock()
   // 设置值
   m.data[key] = value
   return
}

func (m *MemorySession) Get(key string) (value interface{}, err error) {
   m.rwlock.Lock()
   defer m.rwlock.Unlock()
   value, ok := m.data[key]
   if !ok {
      err = errors.New("key not exists in session")
      return
   }
   return
}

func (m *MemorySession) Del(key string) (err error) {
   m.rwlock.Lock()
   defer m.rwlock.Unlock()
   delete(m.data, key)
   return
}

func (m *MemorySession) Save(key string) (err error) {
   return
}

memory_session_mgr.go

package session

import(
   "sync"

   uuid "github.com/satori/go.uuid"
   )

//?    MemorySeesionMgr设计:
//?    定义MemorySeesionMgr对象(字段:存放所有session的map,读写锁)
//?    构造函数
//?    Init()
//?    CreateSeesion()
//?    GetSession()

// 定义对象
type MemorySeesionMgr struct {
   sessionMap map[string]Session
   rwlock     sync.RWMutex
}

// 构造函数
func NewMemorySeesionMgr() SessionMgr {
   sr := &MemorySeesionMgr{
      sessionMap: make(map[string]Session, 1024),
   }
   return sr
}

func (s *MemorySeesionMgr) Init(addr string, options ...string) (err error) {
   return
}

func (s *MemorySeesionMgr)CreateSession()(session Session,err error)  {
   s.rwlock.Lock()
   defer s.rwlock.Unlock()
   // go get github.com/satori/go.uuid
   // 用uuid作为sessionId
   id, err := uuid.NewV4()
   if err != nil{
      return
   }
   // 转string
   sessionId := id.String()
   // 创建个session
   session = NewMemorySession(sessionId)

   return
}

func (s *MemorySeesionMgr)Get(sessionId string)(session Session,err error)  {
   return
}

  

 

以上是关于Cookie/Session的主要内容,如果未能解决你的问题,请参考以下文章

JavaWeb学习笔记(狂神版)--- 第九节 Cookie与Session

4.cookie session

sqlHelper做增删改查,SQL注入处理,存储值,cookie,session

cookie、session、redis实现单点登录

Token是啥?和session、cookie相比,使用场景有啥区别?

PHP使用cookie,session和SQL写登陆页面