Dylan的博客

世间所有的相遇,都是久别重逢

0%

一个简单'硬核'的登陆验证三部曲

背景:

一直以来对 登录 => 验证 => 权限 => 页面跳转 模糊不清

最近接手了一个CRA + craco 构建的一个后台管理系统,熟悉了两天,代码真的吃藕…

不行,所以决定重构,也简单整理了登录验证这块的大体思路。

大体思路为:

  • login接口 => 成功拿到 token => 存到 sessionStorage
  • axios.request 拦截器 => 检查如果有token => 放在请求头里发送 headers.accessToken = token
  • axios.response 拦截器 => statusCode 401 => token过期或没有登录权限 => history.push(‘/login’)

login

登录方法的代码就不展示了,不同的项目有不同的写法,这块知道大体思路就好。

1
axios('/login').then(res=> sessionStorage.setItem('token',res.token));

axios.interceptors.request

1
2
3
4
5
6
7
8
9
10
11
12
13
//如果token存在就放到header里(只展示了相关代码),每次请求都存入token,由后台判断是否过期需要重新登录。

axios.interceptors.request.use(
(config) => {
if(sessionStorage.getItem('token')){
config.headers.accessToken = sessionStorage.getItem("token");
}
return config;
},
(error) => {
return Promise.reject(error);
}
);

axios.interceptors.response

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
63
64
65
66
67
// 因为 checkResponseCode 逻辑太多所以抽离了出去

axios.interceptors.response.use(
(response: AxiosResponse): any => checkResponseCode(response),
function (error) {
// 对响应错误做点什么
return Promise.reject(error);
}
);


// checkResponseCode.ts

function checkResponseCode(response) {
const { status, data } = response;
switch (true) {
//401
case status === HTTP_STATUS_CODES.UNAUTHORIZED: {
const { url = "/login" } = data || {};
window.location.href = window.location.origin + url;
return { status: RESPONSE_STATUS.NOT_LOGGED_IN, url };
}

//其他statusCode判断...

default: {
return { status: RESPONSE_STATUS.SUCCESS, page: data.page, data };
}
}
}

到这里就可实现一个简单的登录验证啦! 我这里url默认了 '/login' 具体情况以自己项目为主。




其中 HTTP_STATUS_CODESRESPONSE_STATUS 均为枚举。

const HTTP_STATUS_CODES = {
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
FORBIDDEN: 403,
NOT_FOUND: 404,
REQUEST_TIME_OUT: 408,
CONFLICT: 409,
UNPROCESSABLE_ENTITY: 422,
INTERNAL_SERVER_ERROR: 500,
GATEWAY_TIMEOUT: 504,
};

enum RESPONSE_STATUS {
"ERROR" = "ERROR",
"INVALID" = "INVALID",
"REQUEST" = "REQUEST",
"SUCCESS" = "SUCCESS",
"LOADED" = "LOADED",
"FAILURE" = "FAILURE",
"LOGOUT" = "LOGOUT",
"NOT_FOUND" = "NOT_FOUND",
"FIELD_INVALID" = "FIELD_INVALID",
"NOT_LOGGED_IN" = "NOT_LOGGED_IN",
"NO_ACCESS" = "NO_ACCESS",
"EXCEPTION" = "EXCEPTION",
"REDIRECT" = "REDIRECT",
"INTERNAL_SERVER_ERROR" = "INTERNAL_SERVER_ERROR",
"RESOURCE_LOAD_ERROR" = "RESOURCE_LOAD_ERROR",
}

以上是我整理的大体思路和极简版的代码,后续可能还会有优化,和增加路由守卫等鉴权功能。