鉴权与相关 API 接口封装

意为authentication 鉴权,区别于authorization 授权


大纲链接 §

[toc]


基础准备知识

  • 命令行基础
  • ES6基础语法
  • HTTP基础 请求响应 和 AJAX
  • axios基本语法和使用
  • Node.js基础
    • *略微了解Express.js
    • *略微了解KOA.js - 版本KOA2

数据请求接口封装 JWT 身份认证机制

使用axios请求库 + JWT 机制

  • axios文档
    • axios.request(config)
    • axios.get(url[, config])
    • axios.delete(url[, config])
    • axios.head(url[, config])
    • axios.options(url[, config])
    • axios.post(url[, data[, config]])
    • axios.put(url[, data[, config]])
    • axios.patch(url[, data[, config]])
  • localStorage

安装axios

1
2
# yarn add axios
pnpm add axios

创建src/helpers/request.ts,封装发送请求方法

 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import axios, {AxiosRequestConfig, Method} from 'axios';
import {message} from 'ant-design-vue';

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.baseURL = 'https://blog-server.hunger-valley.com';

const errorMsg = (msg: string) => {
  message.error(msg);
};

export default function request(url: string, type: Method = 'GET', data = {}) {
  return new Promise((resolve, reject) => {
    // 配置axios选项参数
    const option: AxiosRequestConfig = {
      url,
      method: type
    };

    // 配置数据
    type.toUpperCase() === 'GET'
      ? option.params = data // 查询参数方式 传递数据
      : option.data = data;

    // 携带JWT
    if (localStorage.token) {
      axios.defaults.headers.common['Authorization'] = localStorage.token;
    }

    axios(option)
      .then(res => {
        console.log(res.data);
        // 接口文档约定 res.data.status: 'ok' 见 http://dw-z.ink/2j4pC
        if (res.data.status === 'ok') {
          res.data.token || (localStorage.token = res.data.token);
          resolve(res.data);
        } else {
          errorMsg(res.data.msg);
          reject(res.data);
        }
      })
      .catch(err => {
        errorMsg('网络异常');
        reject({msg: '网络异常', errorDetail: err});
      });
  });
}
  • UI库使用ant-design-vue
  • 按需引入组件import {message} from 'ant-design-vue';
  • 接口约定,响应返回数据中存在res.data.token,就存入localStorage.token

API接口封装

  • 封装底层数据请求

API接口封装 /auth

 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
28
29
30
// 接口文档见 http://dw-z.ink/2j4pC
import request from '@/helpers/request';

const URL = {
  register: '/auth/register',
  login: '/auth/login',
  logout: '/auth/logout',
  get_info: '/auth',
};

type userAuthInfo = {
  username: string,
  password: string
}

export default {
  register(data: userAuthInfo) {
    return request(URL.register, 'POST', data);
  },
  login(data: userAuthInfo) {
    return request(URL.login, 'POST', data);
  },
  logout() {
    return request(URL.logout);
  },
  getInfo() {
    return request(URL.get_info);
  }
};

API接口封装 /blog

 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// 接口文档见 http://dw-z.ink/2j4pC
import request from '@/helpers/request';
// RESTful API URL
const URL = {
  get_list: '/blog',
  get_detail: '/blog/:blogId',
  create: '/blog',
  update: '/blog/:blogId',
  delete: '/blog/:blogId',
};

type blogInfo = {
  page: number,
  userId?: number,
  atIndex?: boolean
}

type blogDetail = {
  title?: string,
  content?: string,
  description?: string,
  atIndex?: boolean
}

export default {
  getBlogs({page = 1, userId, atIndex}: blogInfo = {page: 1}) {
    return request(URL.get_list, 'GET', {page, userId, atIndex});
  },
  getIndexBlogs({page = 1} = {page: 1}) {
    return this.getBlogs({page, atIndex: true});
  },
  getBlogsByUserId(userId: number, {page, atIndex}: blogInfo = {page: 1}) {
    return this.getBlogs({userId, page, atIndex});
  },
  getDetail({blogId}: { blogId: number }) {
    return request(URL.get_detail.replace(':blogId', `${blogId}`));
  },
  createBlog({title = '', content = '', description = '', atIndex = false} = {
    title: '',
    content: '',
    description: '',
    atIndex: false
  }) {
    return request(URL.update, 'POST', {title, content, description, atIndex});
  },
  updateBlog({blogId}: { blogId: number }, {title, content, description, atIndex}: blogDetail) {
    return request(URL.update.replace(':blogId', `${blogId}`),
      'PATCH',
      {title, content, description, atIndex});
  },
  deleteBlog({blogId}: { blogId: number }) {
    return request(URL.delete.replace(':blogId', `${blogId}`), 'DELETE');
  },
};

// 使用示例
// auth.register({username: hungerXx', password: '123456})
// auth.getInfo({)
// blog.createBlog({title: hungerXx', atIndex: true})
// blog.getBlogs()
// blog.getBlogsByUserId(6)


问答

  1. 网站常见的鉴权认证方式有哪几种?
  2. Session认证的原理?
  3. JWT认证的原理?
  4. Auth2认证的流程?
  5. JWT相比Session机制有哪些缺点?
  6. Session机制如何能尽量保证安全?
  7. 针对Web的攻击技术
  8. XSS攻击原理
  9. CSRF攻击原理


参考文章

相关文章


  • 作者: Joel
  • 文章链接:
  • 版权声明
  • 非自由转载-非商用-非衍生-保持署名