basic 原理及实现

basic 原理及实现

basic 认证是 HTTP 身份验证 方法之一. 使用 header 如下:

WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>

type 指的是验证的方案, realm 用来描述进行保护的区域. type 值可以为:

  • Basic (查看 RFC 7617, base64编码凭证.), 即本文要讲的内容,
  • Bearer (查看 RFC 6750, bearer 令牌通过OAuth 2.0保护资源),

Basic HTTP 验证方案是在 RFC 7617中规定的,在该方案中,使用用户的 ID/密码作为凭证信息,并且使用 base64 算法进行编码,但base64可逆向所以并不安全。

nodejs 原生实现 basic 认证

运行以下代码, 浏览器打开 http://127.0.0.1:8888/ , 输入用户名 123 密码 456, 即可正常看到 yes, 否则看到 no.

实现步骤:

  • 前端把 用户名:密码 信息编码为 base64 拼接 Basic 放到请求头 authorization 中
  • 接口获取 base64 进行解码
  • 如果不是有效的信息, 则返回 401 并且设置响应头为 WWW-Authenticate: Basic realm="", 浏览器则要求输入用户信息
  • 如果信息有效, 返回正常的内容即可
const http = require('http');
http.createServer((req, res) => {
  const token = req.headers.authorization || ``
  const [user, password] = getInfo({token})
  console.log(`用户信息`, {token, user, password})
  if(user === `123` && password === `456`) {
    res.end('yes');
  } else {
    // 状态码 401 并且响应头 `WWW-Authenticate: Basic realm=""` 时浏览器就会提示登录
    res.writeHead(401, { 'WWW-Authenticate': 'Basic realm=""' });
    res.end('no');
  }
}).listen(8888, () => {
  console.log(`http://127.0.0.1:8888/`)
});

function getCode({ user = `123`, password = `456` }) { // 把 user:password 编码为 base64
  let auth = `${user}:${password}`
  const buf = Buffer.from(auth, 'ascii');
  const base64 = buf.toString('base64')
  return `Basic ${base64}`
}

function getInfo({ token = `Basic MTIzOjQ1Ng==` }) { // 解码 base64
  const buf = Buffer.from(token.split(/s+/).pop(), 'base64');
  const authString = buf.toString('ascii');
  return authString.split(':');
}

优点和缺点

一些应用可以支持 url 授权方式, 例如 https://username:password@www.example.com/ , 但这种方式不推荐使用并已在大多浏览器中废弃.

优点:

  • 使用非常简单
  • 开发和调试工作简单
  • 没有复杂的页面跳转逻辑和交互过程
  • 更利于发起方控制

缺点:

  • base64 可逆向,容易直接看到明文
  • 本地和服务器需要同时保存密码, 有一方更改另一方也需要更改
  • 未来可能被废弃(url 授权方式已被废弃)

参考

原文地址:https://www.cnblogs.com/daysme/p/14864182.html