一文读懂Cookie和Session

569 阅读8分钟

Cookie

一、Cookie的介绍

  • 1、HTTP 是无状态协议。简单地说,当你浏览了一个页面,然后转到同一个网站的另一个页 面,服务器无法认识到这是同一个浏览器在访问同一个网站。每一次的访问,都是没有任何关系的。如果我们要实现多个页面之间共享数据的话我们就可以使用 Cookie 或者 Session 实 现

  • 2、cookie 是存储于访问者的计算机中的变量。可以让我们用同一个浏览器访问同一个域名的时候共享数据。

  1. Cookie 是一种客户端存储机制,用于在客户端(浏览器)和服务器之间传递信息。在同源策略中,Cookie 也受到了限制。

二、Cookie的特点

  • cookie 保存在浏览器本地
  • 正常设置的 cookie 是不加密的,用户可以自由看到;
  • 用户可以删除 cookie,或者禁用它
  • cookie 可以被篡改
  • cookie 可以用于攻击
  • cookie 存储量很小。实际上要被localStorage替代,但是后者 IE9 兼容。

三、Cookie的属性

下面是常用的 Cookie 属性及其含义:

  • Domain:指定 Cookie 的作用域。只有在指定的域名下才能访问该 Cookie。如果不设置该属性,则默认为当前请求的域名。
  • Path:指定 Cookie 的作用路径。只有在指定的路径下才能访问该 Cookie。如果不设置该属性,则默认为当前请求的路径。
  • Expires:指定 Cookie 的过期时间。该属性的值为一个 GMT 格式的时间字符串,表示该 Cookie 在何时过期。如果不设置该属性,则该 Cookie 会在浏览器关闭后自动删除。
  • Max-Age:指定 Cookie 的过期时间。该属性的值为一个整数,表示该 Cookie 在多少秒后过期。如果设置了 Max-Age 属性,则会覆盖 Expires 属性。
  • Secure:指定该 Cookie 只能通过 HTTPS 协议传输。如果不设置该属性,则该 Cookie 可以通过 HTTP 协议和 HTTPS 协议传输。
  • HttpOnly:指定该 Cookie 只能通过 HTTP 协议访问,不能通过 JavaScript 访问。这样可以防止 XSS 攻击窃取 Cookie 的值。
  • SameSite:指定该 Cookie 的 SameSite 属性。SameSite 属性可以有三个值:StrictLaxNoneStrict 表示该 Cookie 只能在同源请求中发送;Lax 表示该 Cookie 在跨域情况下只能在 GET 请求中发送,POST 请求需要满足一定条件才能发送;None 表示该 Cookie 可以在跨域请求中发送。

这些属性可以通过 Set-Cookie 响应头来设置,例如: Set-Cookie: name=value; Domain=example.com; Path=/; Max-Age=3600; Secure; HttpOnly; SameSite=Lax

Cookie 与 同源策略

同源策略是浏览器的一项安全功能,它用于限制不同源(域名、协议或端口不同)之间的文档或脚本的交互。同源策略的目的是为了保护用户的隐私和安全。在同源策略中,Cookie 只能在同源(域名、协议或端口相同)之间共享。

这意味着,如果一个网站设置了一个 Cookie,该 Cookie 就只能在该网站的同源网页中访问。其他网站不能访问该 Cookie。例如,如果一个网站的域名是 example.com,它设置了一个 Cookie,该 Cookie 的作用域是 example.com,那么其他域名(例如:test.com)就不能访问该 Cookie。

虽然同源策略对 Cookie 的访问进行了限制,但是可以通过跨域资源共享(CORS)等技术来解决这个问题。CORS 允许服务器控制哪些源可以访问其资源,从而使不同源之间可以共享资源。但是,即使使用了 CORS,Cookie 也必须遵守同源策略的规定。

  1. 在 HTTP 协议中,Cookie 是通过 Set-Cookie 响应头部设置的,它可以包含多个属性,其中就包括 Path 属性。

Path 属性指定了 Cookie 的作用路径。当客户端发送请求时,如果该请求的 URL 匹配了 Cookie 的作用路径,则该 Cookie 会被发送到服务器端。如果请求的 URL 与 Cookie 的作用路径不匹配,则浏览器不会发送该 Cookie。

例如,如果某个网站设置了一个 Cookie,它的 Path 属性为 /foo,则该 Cookie 只会在请求路径为 /foo 或者 /foo/xxx 的页面中发送到服务器端,而不会在其他路径下发送。这样可以限制 Cookie 只在特定的路径中使用,提高了 Cookie 的安全性。

需要注意的是,Path 属性是以一个 URL 路径作为 Cookie 的作用范围,而不是以一个域名为作用范围。也就是说,如果一个网站在不同的路径下设置了相同名称的 Cookie,它们是相互独立的,不会相互干扰。同时,如果一个 Cookie 的 Path 属性设置为 /,则该 Cookie 可以在整个网站中使用。

因此,Path 属性是 Cookie 的一个重要属性,可以限制 Cookie 的作用范围,提高 Cookie 的安全性和可靠性。

Nestjs中使用Cookie

  • 1、cookie-parser地址

  • 2、下载

    npm install cookie-parser
    npm install @types/cookie-parser -D
    

cookic-parser的参数说明

NO.参数类型参数说明
1domainString指定域名下有效
2expiresDate过期时间(秒),设置在某个时间点后会在该cookoe后失效
3httpOnlyBoolean默认为false表示不允许客户端(通过js来获取cookie)
4maxAgeString最大失效时间(毫秒),设置在多少时间后失效
5pathString表示cookie影响到的路径,如:path=/如果路径不能匹配的时候,浏览器则不发送这个cookie
6secureBoolean当 secure 值为true 时,cookie 在 HTTP 中是无效,在 HTTPS中才有效
7signedBoolean表示是否签名cookie,如果设置为true的时候表示对这个cookie签名了,这样就需要用res.signedCookies()获取值cookie不是使用res.cookies()

如果要销毁cookie常见的方式

  • 直接将值设置为空

  • 设置maxAge=0

  • 3、在main.ts中使用

    // 导包
    import * as cookieParser from 'cookie-parser';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      // 使用
      app.use(cookieParser());
      await app.listen(3000);
    }
    bootstrap();
    
  • 4、在组件的控制器中写入和获取cookie

    import { Controller, Get, Response, Request } from '@nestjs/common';
    
    @Controller('user')
    export class UserController {
      @Get()
      index(@Request() req) {
        console.log(req.cookies.name, '当前的cookie');
        return '主页';
      }
    
      @Get('login')
      login(@Response() res) {
        // 如果使使用了res就不能使用return,必须使用send
        res.cookie('name', 'hello', { maxAge: 1000 * 5, httpOnly: true });
        res.send('登录页面');
      }
    }
    
  • 5、在浏览器控制图查看cookie

    到了时间刷新浏览器控制图上的刷新的,cookie就会被清空的

    输入图片说明

Nestjs中使用session

  • 1、session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而 session 保存 在服务器上

  • 2、session的工作流程
    当浏览器访问服务器并发送第一次请求的时候,服务器端会创建一个session对象,生成一个类似于{key: '', value: ''}的对象,然后将key(cookie)返回到浏览器(客户)端,浏览器再次访问的时候携带这个key(cookie)到服务器端,找到这个sessionvalue值。

  • 3、在nestjs中使用express-session进行session的操作

    npm install express-session
    npm install @types/express-session -D
    
  • 4、在main.ts中配置session

    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    import * as session from 'express-session';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      // 配置中间件使用session,加盐是123456(随便写的)
      app.use(session({ secret: '123456', cookie: { maxAge: 60000 } }))
      await app.listen(3000);
    }
    bootstrap();
    

    使用app.use(session({ secret: '123456', cookie: { maxAge: 60000 } }))开启了表示服务器开启了session 当浏览器第一次请求的时候服务器会响应一个cookie用来作为此次连接的凭证,以后每次请求浏览器都会带着这个凭证,这样服务器就能识别浏览器了,相当于php里面的session_start()

image.png image.png Cookie: connect.sid=s%3AFK-7NF03A6PGM85rQQ8ixAZarIe_hsGI.JIizzuGr%2BYljCwghdWn02U5PODapnIThVeF1m%2BnWUCY

  • 5、创建user的模块及控制器(忽视请求方式,只是方便浏览器模拟请求)

    import { Controller, Get, Request, Response } from '@nestjs/common';
    
    @Controller('user')
    export class UserController {
      @Get()
      index(
        @Request() req: { [key: string]: any }
      ): string {
        console.log(req.session);
        return '用户主页';
      }
    
      @Get('login')
      login(
        @Response() res: { [key: string]: any },
        @Request() req: { [key: string]: any }
      ): void {
        req.session.name = 'hello';
        // 再次提醒使用了@Response就不能使用return
        res.send('登录页面')
      }
    }
    
  • 6、先在浏览器中访问localhost:3000/user/login然后访问localhost:3000/user

    // 编辑器控制图打印出信息,可以获取到刚刚设置的session
    Session {
      cookie: {
        path: '/',
        _expires: 2020-07-27T09:28:20.046Z,
        originalMaxAge: 60000,
        httpOnly: true
      },
      name: 'hello'
    }
    
  • 7、常见参数的说明

NO参数说明
1secret一个 String 类型的字符串,作为服务器端生成session 的签名
2name返回客户端的key 的名称,默认为connect.sid,也可以自己设置
3resave强制保存 session即使它并没有变化,。默认为true。建议设置成 false
4saveUninitalized强制将未初始化的 session 存储。当新建了一个 session 且未设定属性或值时,它就处于 未初始化状态。在设定一个 cookie 前,这对于登陆验证,减轻服务端存储压力,权限控制是有帮助的。( 默认:true)。建议手动添加
5cookie设置返回到前端key 的属性,默认值为{ path: ‘/’, httpOnly: true, secure: false, maxAge: null }
6rolling在每次请求时强行设置 cookie,这将重置cookie 过期时间(默认:false)
  • 8、session的销毁

  • 设置maxAge=0

    req.session.cookie.maxAge=0
    
  • 将值设置为空

  • 使用destroy销毁方法

    req.session.destroy((err) => {
      ...
    })