登录凭证cookie、session、token的Koa实现

一.cookie

 1.1. 认识cookie

1.2. cookie常见属性

1.3. cookie客户端设置

  • 在浏览器中通过js设置cookie(在开发中很少使用)
  • 没有设置max-age时, 是一个内存cookie, 浏览器关闭时会消失
  • 设置max-age时, 是一个硬盘cookie, 只能等到过期时间到达的时候, 才会销毁
document.cookie = "name=why;max-age=30;"
document.cookie = "age=18;max-age=60;"

1.4 cookie服务器设置

  • 服务器设置cookie

Koa 中默认支持直接操作 cookie

  • 浏览器接受cookie, 并且客户端保存

  • 在之后的作用域其他网络请求, 会自动携带cookie

  • 服务器获取cookie, 并且验证cookie

const Koa = require('koa')
const KoaRouter = require('@koa/router')

const app = new Koa()

const userRouter = new KoaRouter({ prefix: '/users' })

/**
 * 1.服务器设置cookie
 * 2.客户端(浏览器)保存cookie
 * 3.在同一个作用域下访问服务器, 自动携带cookie
 * 4.服务器验证客户端携带的cookie
 */
userRouter.get('/login', (ctx, next) => {
  // 在服务器中为登录的客户端, 设置一个cookie
  ctx.cookies.set('slogan', 'ikun', {
    maxAge: 60 * 1000 * 5
  })

  ctx.body = '登录成功~'
})

userRouter.get('/list', (ctx, next) => {
  // 验证用户的登录凭证: 携带口号 ikun
  const value = ctx.cookies.get('slogan')
  console.log(value)
  if (value === 'ikun') {
    ctx.body = `user list data~`
  } else {
    ctx.body = `没有权限访问用户列表, 请先登录~`
  }
})

app.use(userRouter.routes())
app.use(userRouter.allowedMethods())

app.listen(8000, () => {
  console.log('服务器启动成功~')
})

二、session

 2.1 服务器使用session

  • 基于cookie

  • cookie中信息和内容进行加密处理, 加密签名

  • 早期登录凭证: cookie+session

const Koa = require('koa');
const KoaRouter = require('@koa/router');
const koaSession = require('koa-session');

const app = new Koa();

const userRouter = new KoaRouter({ prefix: '/users' });

const session = koaSession (
  {
    key: 'sessionid', //cookie的key
    maxAge: 5 * 1000, //过期时间
    httpOnly: true, //不允许通过js获取cookie
    rolling: true, // 每次响应时,刷新session的有效期
    signed: true, // 是否使用signed签名认证,防止数据被篡改
  },
  app
);

// 加盐操作
app.keys = ['aaa', 'bbb', 'why', 'kobe'];
app.use(session);

userRouter.get('/login', (ctx, next) => {
  // 在服务器中为登录的客户端, 设置一个cookie
  ctx.session.slogan = 'ikun';

  ctx.body = '登录成功~';
});

userRouter.get('/list', (ctx, next) => {
  // 验证用户的登录凭证: 携带口号 ikun
  const value = ctx.session.slogan;
  console.log(value);
  if (value === 'ikun') {
    ctx.body = `user list data~`;
  } else {
    ctx.body = `没有权限访问用户列表, 请先登录~`;
  }
});

app.use(userRouter.routes());
app.use(userRouter.allowedMethods());

app.listen(8000, () => {
  console.log('服务器启动成功~');
});

2.2  cookie+session缺点

 

三、 token的颁发和验证

3.1  jsonwebtoken 生成token

const jwt = require('jsonwebtoken') 
const token = jwt.sign(payload, secretkey, {
    expiresIn: 60
  })

 ​​​​​​

JWT生成的 Token 由三部分组成:

header

  • alg:采用的加密算法,默认是 HMAC SHA256 (HS256 ),采用同一个密钥进行加密和解密(对称加密)
  • typ:JWT ,固定值,通常都写成 JWT 即可;
  • 会通过base64Url 算法进行编码;


payload

  • 携带的数据,比如我们可以将用户的id 和 name 放到 payload 中;
  • 默认也会携带   iat (issued at ),令牌的签发时间
  • 我们也可以设置过期时间:exp (expiration time)
  • 会通过base64Url 算法进行编码


signature 

  • 设置一个secretKey ,通过将前两个的结果合并后进行 HMACSHA256 的算法;
  • HMACSHA256(base64Url(header)+.+base64Url(payload),secretKey);
  • 但是如果secretKey 暴露是一件非常危险的事情,因为之后就可以模拟颁发 token ,也可以解密 token

3.2 获取客户端携带的token

  const authorization = ctx.headers.authorization
  const token = authorization.replace('Bearer ', '')
  console.log(token)

  postman 模拟客户端携带token

 实际 token  在 headers.authorization 字段中

 

3.3 验证 token,获取用户信息

const result = jwt.verify(token, secretkey)

3.4 缺点: 对称加密 

默认使用的HS256 加密算法是对称加密算法,加密和解密都是同一个密钥,一旦密钥暴露就是非常危险的事情:

  • 比如在分布式系统中,每一个子系统都需要获取到密钥;
  • 那么拿到这个密钥后这个子系统既可以发布另外,也可以验证令牌;
  • 但是对于一些资源服务器来说,它们只需要有验证令牌的能力就可以了;

  完整实现代码

const Koa = require('koa')
const KoaRouter = require('@koa/router')
const jwt = require('jsonwebtoken')

const app = new Koa()

const userRouter = new KoaRouter({ prefix: '/users' })

const secretkey = 'aaabbbccxxxx'

userRouter.get('/login', (ctx, next) => {
  // 1.颁发token
  const payload = { id: 111, name: 'why' }
  const token = jwt.sign(payload, secretkey, {
    expiresIn: 60   //过期时间
  })

  ctx.body = {
    code: 0,
    token,
    message: '登录成功, 可以进行其他的操作'
  }
})

userRouter.get('/list', (ctx, next) => {
  // 1.获取客户端携带过来的token
  const authorization = ctx.headers.authorization
  const token = authorization.replace('Bearer ', '')
  console.log(token)

  // 2.验证token
  try {
    const result = jwt.verify(token, secretkey)
    
    ctx.body = {
      code: 0,
      data: [
        { id: 111, name: 'why' },
        { id: 111, name: 'why' },
        { id: 111, name: 'why' },
      ]
    }
  } catch (error) {
    ctx.body = {
      code: -1010,
      message: 'token过期或者无效的token~'
    }
  }
})

app.use(userRouter.routes())
app.use(userRouter.allowedMethods())

app.listen(8000, () => {
  console.log('服务器启动成功~')
})

3.5. 非对称加密颁发令牌

可以使用非对称加密,RS256

  • 私钥( private key ):用于发布令牌
  • 公钥( public key ):用于验证令牌

我们可以使用 openssl 来生成一对私钥和公钥:
Mac 直接使用 terminal 终端即可;
Windows默认的 cmd 终端是不能直接使用的,建议直接使用 git bash 终端;

openssl
>
genrsa -out private.key 1024
>
rsa -in private.key -pubout -out public.key
  • 读取私钥和公钥
const fs = require('fs')
const privateKey = fs.readFileSync('./keys/private.key')
const publicKey = fs.readFileSync('./keys/public.key')
  •  颁发 token ,用私钥 privateKey 进行加密
const token = jwt.sign(payload, privateKey, {
    expiresIn: 60,   //token有效时间
    algorithm: 'RS256'  //加密算法
  })
  • 验证 token 用公钥 publickey 进行解密
const result = jwt.verify(token, publicKey, {
      algorithms: ['RS256']
    })

 完整代码

const fs = require('fs')
const Koa = require('koa')
const KoaRouter = require('@koa/router')
const jwt = require('jsonwebtoken')

const app = new Koa()

const userRouter = new KoaRouter({ prefix: '/users' })

const privateKey = fs.readFileSync('./keys/private.key')
const publicKey = fs.readFileSync('./keys/public.key')

userRouter.get('/login', (ctx, next) => {
  // 1.颁发token
  const payload = { id: 111, name: 'why' }
  const token = jwt.sign(payload, privateKey, {
    expiresIn: 60,
    algorithm: 'RS256'
  })

  ctx.body = {
    code: 0,
    token,
    message: '登录成功, 可以进行其他的操作'
  }
})

userRouter.get('/list', (ctx, next) => {
  // 1.获取客户端携带过来的token
  const authorization = ctx.headers.authorization
  const token = authorization.replace('Bearer ', '')
  console.log(token)

  // 2.验证token
  try {
    const result = jwt.verify(token, publicKey, {
      algorithms: ['RS256']
    })
    
    ctx.body = {
      code: 0,
      data: [
        { id: 111, name: 'why' },
        { id: 111, name: 'why' },
        { id: 111, name: 'why' },
      ]
    }
  } catch (error) {
    console.log(error)
    ctx.body = {
      code: -1010,
      message: 'token过期或者无效的token~'
    }
  }
})

app.use(userRouter.routes())
app.use(userRouter.allowedMethods())

app.listen(8000, () => {
  console.log('服务器启动成功~')
})

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: CookieSession Token 在 Web 应用中都被用来跟踪用户状态。两者的主要区别在于,Cookie 是存储在用户设备上的,而 Session Token 则是存储在服务器端的。 Cookie 是由浏览器自动创建和发送给服务器的,用户可以在浏览器的设置中查看和管理它们。Cookie 中可以存储一些键值对数据,在用户的不同请求之间共享数据。Cookie 适用于存储一些简单的数据,例如用户名和密码等。 Session Token 是在用户登录时在服务器端创建,并在用户与服务器进行交互时发送。服务器端会为每个用户维护一个唯一的 Session TokenSession Token 是在服务器端存储的,用户可以在浏览器中查看,但不能编辑或删除。Session Token 适用于存储用户身份,例如权限、购物车等。 总结,Cookie主要用来存储简单的,不太敏感的数据,且存在浏览器端;而Session token用来标识用户身份,数据都是存在服务器端。 ### 回答2: cookiesessiontoken都是现在常见的认证方式,用于保证Web应用程序的安全性和隐私性。在理解三者的区别之前,需要先了解它们的基本概念含义。 1. Cookie Cookie 是服务器发送给浏览器的小型数据文件,存储在用户的计算机中。浏览器在之后的请求中会将此文件发送到服务器,以便于验证用户的身份和记录用户的行为。 Cookie 的优点在于它可以存储比 Session 更多的信息,并且可以在浏览器关闭后仍然保持数据有效。缺点是 Cookie 可以被恶意软件或黑客轻易窃取。 2. Session Session 指的是服务器创建的一个会话过程,用于在特定时间段内记录某个用户的交互状态。通过 Session,Web应用程序可以在不同的页面之间共享数据,为用户提供个性化服务。 Session 的优点在于它存储在服务器上,保障了比 Cookie 更好的安全性和隐私性。但是, Session 也会消耗服务器的资源,因此需要谨慎管理。 3. Token Token 是一种随机生成的字符串,用于验证用户的身份和权限。在 Web 应用程序中,Token 可以被用来替代 CookieSession,因为它不会存储在用户的计算机中,也不需要服务器存储用户的状态。 Token 的优点在于它们相对更安全,因为它们没有任何销售性的信息存储在用户的浏览器中。另外, Token 机制可以支持无状态应用,也就是应用程序无需保存任何会话信息,更好的支持了分布式架构。 在以上区别基础上,三者的区别主要在于存储地点(客户端或服务器端)、存储内容(数据信息)、安全性和使用场景等。 - Cookie主要存储在客户端,并可以将更多的数据存储在客户端,Session存储于服务端提供了更好的安全性,但会占用更多服务器资源,Token能够将Session信息存储于客户端,也可以保证数据安全。 - Cookie主要用于客户端与服务端的交互;Session更注重用户身份的鉴别与用户状态的维护;Token更多地用于 API 认证。 - 一般情况下Cookie的安全性最低,Session的安全性中等,Token相对而言较为安全。 - 通常情况下,Token方式的应用程序可以跨平台、跨域和分布式部署,更加灵活多变。 综上所述,Cookiesessiontoken都是Web开发中常用的验证方式,它们在存储及应用方式上均有所差别。仔细分析自身需求,选择最适合的认证方式相比盲目跟随更为优合理。 ### 回答3: CookieSessionToken都是web应用中常见的身份认证和信息存储方式,它们之间最大的不同在于其存储的位置和方式。 Cookie是由服务器在浏览器中生成的,并存储在浏览器中的文件中。当浏览器向服务器发出请求时,会自动通过Cookie中的信息向服务器证明身份。Cookie在用户登录后会保存用户名、密码和一些其他信息,以便下次登录时自动填充,从而提高用户体验。 Session是一个服务器端的解决方案,它可以在服务器端存储用户的会话信息,并且在用户进行请求时将信息传输到客户端。Session实现依赖于Cookie,服务器通过发送一个包含Session ID的Cookie,来记录用户的会话信息,服务器则将Session信息保存在服务器端的内存或者文件系统中,以确保用户信息的安全性。 Token是一种无状态的身份认证方式,它不同于CookieSession的保存信息方式,而是保存在客户端中。当用户登录时,服务器会生成一个Token并将其返回给客户端,客户端在后续的请求中会带上这个Token,服务器会通过验证Token的合法性来判断用户的身份。 总的来说,Cookie是一种简单且易用的Web身份认证方式,Session需要服务器支持,可以更好的保证用户信息的安全性,Token则更适合Web接口/移动端API身份认证。不同的应用场景可以选择适合的认证方式,以确保用户信息和身份的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值