basic 原理及实现
basic 认证是 HTTP 身份验证
方法之一. 使用 header 如下:
WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>
type 指的是验证的方案, realm 用来描述进行保护的区域. type 值可以为:
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 授权方式已被废弃)