React多个系统之间登录登出逻辑的实现

本文介绍 React 登录登出逻辑的一种实现方法。

用户在注册页面进行注册表单提交,正确提交信息后,进入登录页面,登录页面检测用户是否已经登录(此处有多种方法,可以检测 cookie,我用的是检测 localStorage 是否有我登录时存的一个值)。

如果直接在地址栏输入地址,检测到未登录状态,则返回到登录页面。

在其他功能页面每次向服务端发送数据请求的时候,都在请求 header 里面加上 token,如果服务端返回 401,则按照下面的 http response 拦截处理,返回登录页面

axios 拦截

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
// http request 拦截器
axios.interceptors.request.use(
(config) => {
if (store.state.token) {
// 判断是否存在token,如果存在的话,则每个http header都加上token
config.headers.Authorization = `token ${store.state.token}`;
}
return config;
},
(err) => {
return Promise.reject(err);
}
);

// http response 拦截器
axios.interceptors.response.use(
(response) => {
return response;
},
(error) => {
if (error.response) {
switch (error.response.status) {
case 401:
// 返回 401 清除token信息并跳转到登录页面
// message.error('登录超时,请重新登录');
setTimeout(() => {
history.push('/login');
}, 1000);
case 500:
history.push('/servererror');
}
}
return Promise.reject(error.response.data); // 返回接口返回的错误信息
}
);

在请求的 url 里面直接加 token

需求是在 A 系统的页面通过点击事件跳转到 B 系统的页面,所以不能用 router 来做。

这里前端通过 token 与时间戳拼接加密(用的是 base64 对称加密,方便后端解密),然后将加密后的 token 直接添加到 url 的参数里面。

1
2
3
4
5
6
// A系统
import Base64 from 'base-64';
let time = new Date().valueOf();
let temp = window.localStorage.token + '+' + time;
let code = Base64.encode(temp);
window.open(`${API}/example?token=${code}`);

在 B 系统的首页,先后通过对 url 的拆分、decode 解密、再与时间戳分离,获取到 token,再发请求给后端校验权限,如果没有权限,则跳回到 A 系统的登录界面。

这样的话,用户就不能通过复制 B 系统链接的方式绕过 A 系统的登录。

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
// B系统
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
intervalId: null,
currentCount: 2,
};
}
//组件未挂载前就发送请求,验证身份
componentWillMount() {
const url = window.location.href;
const code = url.substring(url.indexOf('=') + 1);
const tokenAndTime = Base64.decode(code);
const token = tokenAndTime.split('+')[0];
localStorage.setItem('token', token);
axios.interceptors.response.use(); //和上面的response拦截一样
axios({
method: 'get',
url: `https://www.example.com/api`,
headers: { Authorization: token },
}).then((response) => {
//处理返回数据
});
}
//组件挂载后定时执行
componentDidMount() {
//50分钟校验一次token有没有过期
let intervalId = setInterval(this.timer, 3000000);
this.setState({ intervalId: intervalId });
}
componentWillUnmount() {
clearInterval(this.state.intervalId);
}
timer() {
const storage = window.localStorage;
let newCount = this.state.currentCount - 1;
if (newCount >= 0) {
axios({
method: 'get',
url: `https://www.example.com/api`,
headers: { Authorization: storage.token },
}).then((response) => {
if (response.data.code === 200) {
console.log('token有效');
} else {
console.log('token失效');
window.location.href = 'https://www.A.com';
}
});
this.setState({ currentCount: newCount });
} else {
clearInterval(this.state.intervalId);
}
}
}

应该会有更好的实现方式,这里就算是抛砖引玉了。

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2018-2020 Jee
  • Visitors: | Views:

如果您觉得此文章帮助到了您,请作者喝杯咖啡吧~

支付宝
微信