HTTP Basic Authentication

身份验证又称鉴权,是获取一个资源前的一个校验过程。比如你要进入一栋锁着的房子,必须通过拿出钥匙开锁才能进入。这里的”钥匙“我们一般称为”凭据“(token)。我们开发过程中会使用很多种不同的鉴权方案,具体实现一般跟业务相关。Http 协议自身也约定了一些鉴权方式,让我们来看看吧。

Http 基础验证

HTTP Basic Authentication 顾名思义是一种非常简单的基础验证协议。

基础到什么程度呢?它是将用户的账号和密码通过用户名:密码拼接后再进行 base64 加密后,放到 http 头部进行传输。由于 base64 编码是可逆的,意味着账号密码是在网络中明文传输的,所以一般需要通过 https 来保证传输过程的安全。

下面我们用 nodejs 来实现 Basic 验证

1
2
3
4
5
6
7
8
9
10
11
12
13
const { createServer } = require('http');

const server = createServer((req, res) => {
res.writeHead(401, {
'WWW-Authenticate': 'Basic realm="test"',
});
res.write('401 Authorization Required');
res.end();
});

server.listen('5000', () => {
console.log('> listen on http://localhost:5000');
});

我们打开浏览器,访问 http://localhost:5000 得到如下

demo1

浏览器之所以知道需要弹出个窗口,是因为我们在响应头中返回了WWW-Authenticate,这个头部是 http 身份验证的一部分。

WWW-Authenticate

定义了使用何种验证方式去获取对资源的连接。它的格式如下:

1
[type] realm=<realm>
  • type 鉴权的类型,比较常用的有BasicBearer,查看所有所有的类型点击这里
  • reaml 一个保护区域的描述。用于 server 区分不同的校验,个人理解对于客户端来说这个参数是没有直接用处的。

添加验证

我们完善上面代码,加入对authorization请求头的解析,解析出账号密码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const server = createServer((req, res) => {
const authorization = req.headers['authorization'];

if (authorization) {
const [username, password] = Buffer.from(
authorization.split(' ')[1],
'base64'
)
.toString('utf-8')
.split(':');

if (
reamls['test'].username === username ||
reamls['test'].password === password
) {
res.write('200 hello world');
res.end();
return;
}
}

res.writeHead(401, {
'WWW-Authenticate': `Basic realm="test2"`,
});
res.write('401 Authorization Required');
res.end();
});

输入账号密码后,可以看到请求头添加了authroize字段。

demo1

这个就是浏览器生成的访问凭据,一般来说,在浏览器关闭前会一直存在。

凭据是保存在浏览器内部的,而不是用的 cookie,localstorage 等存储方式。

basic 验证由于采用账号密码明文传输,注定是一种不会长久的验证方式。下面我们将会学习OAuth 2.0

参考文档