jwt,cookie,session的异同,以及在golang中的实现

概要

JWT、Cookie、Session 的异同点

存储位置与结构

JWT (JSON Web Token)

  • 存储在客户端(如LocalStorage或Cookie中),由三部分组成:Header(算法类型)、Payload(数据)、Signature(签名验证)。
  • 数据以Base64编码的JSON形式存在,可自包含用户信息,无需服务端存储。

Cookie

  • 由服务端生成并存储在客户端(浏览器),通过HTTP头部(Set-Cookie)传递。
  • 键值对形式,可设置过期时间、域名限制等属性。

Session

  • 服务端存储用户状态(如内存、Redis),通过唯一的Session ID标识,ID通常通过Cookie传递到客户端。
  • 数据存储在服务端,客户端仅持有ID。

安全性与验证机制

JWT

  • 依赖签名(如HMAC或RSA)验证完整性,需防范密钥泄露。Payload可被解码但不可篡改。
  • 无状态,但需处理令牌撤销问题(如黑名单)。

Cookie

  • 可设置HttpOnly(防XSS)、Secure(仅HTTPS)、SameSite(防CSRF)。
  • 需防范会话劫持,若泄露则攻击者可冒充用户。

Session

  • 服务端可控会话生命周期,可即时失效。
  • 需防范Session Fixation攻击,需定期更换Session ID。

性能与扩展性

JWT

  • 无状态,适合分布式系统,减少服务端存储开销。
  • 但令牌体积较大,增加网络开销。

Cookie

  • 轻量级,但每次请求自动携带,可能包含不必要的数据。
  • 受浏览器同源策略限制。

Session

  • 服务端存储压力大,需共享存储(如Redis)以支持横向扩展。
  • 高频访问时可能成为瓶颈。

典型应用场景

JWT

  • API认证(如OAuth 2.0)、跨域单点登录(SSO)、无服务端状态的移动端应用。

Cookie

  • 传统Web应用会话管理、跟踪用户行为(如分析工具)。

Session

  • 需服务端控制会话的Web应用(如银行系统),敏感操作需短会话超时。

关键差异总结
  • 存储:JWT和Cookie在客户端,Session数据在服务端。
  • 状态:JWT无状态,Session有状态。
  • 安全:JWT依赖签名,Session依赖服务端管理,Cookie需属性加固。
  • 扩展:JWT适合分布式,Session需集中存储。### 使用Golang实现并发模式

以下是一个使用Golang实现并发模式的示例代码,展示如何使用goroutines和channels进行并发编程:

package main

import (
    "fmt"
    "time"
)

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        fmt.Println("worker", id, "started job", j)
        time.Sleep(time.Second)
        fmt.Println("worker", id, "finished job", j)
        results <- j * 2
    }
}

func main() {
    const numJobs = 5
    jobs := make(chan int, numJobs)
    results := make(chan int, numJobs)

    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs)

    for a := 1; a <= numJobs; a++ {
        <-results
    }
}

Golang中的错误处理

Golang使用显式错误处理,以下是一个错误处理的示例:

package main

import (
    "errors"
    "fmt"
)

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}

func main() {
    result, err := divide(10, 0)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Result:", result)
}

Golang接口实现

Golang的接口是隐式实现的,以下是一个接口示例:

package main

import (
    "fmt"
    "math"
)

type Shape interface {
    Area() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

type Rectangle struct {
    Width, Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func printArea(s Shape) {
    fmt.Println("Area:", s.Area())
}

func main() {
    c := Circle{Radius: 5}
    r := Rectangle{Width: 3, Height: 4}
    
    printArea(c)
    printArea(r)
}

Golang中的JSON处理

Golang提供了内置的JSON支持,以下是JSON处理的示例:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    // JSON编码
    p := Person{Name: "John", Age: 30}
    jsonData, err := json.Marshal(p)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(string(jsonData))

    // JSON解码
    var p2 Person
    err = json.Unmarshal(jsonData, &p2)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Printf("%+v\n", p2)
}

Golang中的HTTP服务器

以下是一个简单的HTTP服务器实现:

package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", helloHandler)
    fmt.Println("Server starting on port 8080...")
    http.ListenAndServe(":8080", nil)
}

理解代码的上下文

要准确判断代码属于JWT、Session还是Cookie,需要分析代码的具体功能和结构。以下是对这三种技术的简要区分:

  • JWT (JSON Web Token):通常用于无状态身份验证,由三部分组成(头部、载荷、签名),以xxxxx.yyyyy.zzzzz形式传输,存储在客户端(如LocalStorage或Cookie)。
  • Session:服务器端存储的用户会话数据,依赖Session ID(通常通过Cookie传递),服务器维护会话状态。
  • Cookie:存储在客户端的小型数据片段,由服务器通过Set-Cookie响应头设置,随请求自动发送到服务器。

常见代码特征

JWT相关代码
  • 生成/签名JWT
    const token = jwt.sign({ userId: 123 }, 'secret_key', { expiresIn: '1h' });
    
  • 验证JWT
    const decoded = jwt.verify(token, 'secret_key');
    
Session相关代码
  • Express-Session配置
    app.use(session({
      secret: 'keyboard_cat',
      resave: false,
      saveUninitialized: true
    }));
    
Cookie相关代码
  • 设置Cookie
    res.cookie('username', 'john', { maxAge: 900000 });
    
  • 读取Cookie
    const username = req.cookies.username;
    

如何判断代码类型

  1. 检查依赖库

    • 使用jsonwebtoken库的代码属于JWT。
    • 使用express-session或类似中间件的代码属于Session。
    • 直接操作req.cookiesres.cookie的代码属于Cookie。
  2. 观察数据结构

    • JWT通常为长字符串且包含点分隔的三部分(如eyJhbGciOi...)。
    • Session操作通常涉及req.session对象。
    • Cookie表现为键值对,通过HTTP头传输。
  3. 传输方式

    • JWT可通过请求头(如Authorization: Bearer <token>)、URL或Cookie发送。
    • Session ID默认通过Cookie传递。
    • Cookie通过Cookie请求头自动发送。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐