HTTP 授权

需求分析

HTTP 协议中的 Authorization 请求 header 会包含服务器用于验证用户代理身份的凭证,通常会在服务器返回 401 Unauthorized 状态码以及 WWW-Authenticate 消息头之后在后续请求中发送此消息头。

axios 库也允许你在请求配置中配置 auth 属性,auth 是一个对象结构,包含 usernamepassword 2 个属性。一旦用户在请求的时候配置这俩属性,我们就会自动往 HTTP 的 请求 header 中添加 Authorization 属性,它的值为 Basic 加密串。 这里的加密串是 username:password base64 加密后的结果。

  1. axios.post('/more/post', {
  2. a: 1
  3. }, {
  4. auth: {
  5. username: 'Yee',
  6. password: '123456'
  7. }
  8. }).then(res => {
  9. console.log(res)
  10. })

代码实现

首先修改一下类型定义。

types/index.ts

  1. export interface AxiosRequestConfig {
  2. // ...
  3. auth?: AxiosBasicCredentials
  4. }
  5. export interface AxiosBasicCredentials {
  6. username: string
  7. password: string
  8. }

接着修改合并规则,因为 auth 也是一个对象格式,所以它的合并规则是 deepMergeStrat

core/mergeConfig.ts

  1. const stratKeysDeepMerge = ['headers', 'auth']

然后修改发送请求前的逻辑。

core/xhr.ts

  1. const {
  2. /*...*/
  3. auth
  4. } = config
  5. if (auth) {
  6. headers['Authorization'] = 'Basic ' + btoa(auth.username + ':' + auth.password)
  7. }

demo 编写

  1. axios.post('/more/post', {
  2. a: 1
  3. }, {
  4. auth: {
  5. username: 'Yee',
  6. password: '123456'
  7. }
  8. }).then(res => {
  9. console.log(res)
  10. })

另外,我们在 server.js 中对于这个路由接口写了一段小逻辑:

  1. router.post('/more/post', function(req, res) {
  2. const auth = req.headers.authorization
  3. const [type, credentials] = auth.split(' ')
  4. console.log(atob(credentials))
  5. const [username, password] = atob(credentials).split(':')
  6. if (type === 'Basic' && username === 'Yee' && password === '123456') {
  7. res.json(req.body)
  8. } else {
  9. res.end('UnAuthorization')
  10. }
  11. })

注意,这里我们需要安装第三方库 atob 实现 base64 串的解码。

至此,ts-axios 支持了 HTTP 授权功能,用户可以通过配置 auth 对象实现自动在请求 header 中添加 Authorization 属性。下一节课我们来实现自定义合法状态码功能。