以下是除了重新登录之外,处理服务器返回的 401 错误的其他方式:
1. 令牌刷新机制
1.1 自动刷新令牌
-
使用刷新令牌获取新的访问令牌:
-
在使用令牌(如 JWT)进行身份验证的系统中,除了之前提到的使用刷新令牌的方法,还可以在后台自动刷新令牌,以避免用户体验中断。例如,使用
setInterval或setTimeout定期刷新令牌。
-
收起
javascript
let refreshInterval;
function startTokenRefresh() {
refreshInterval = setInterval(async () => {
try {
const refreshToken = localStorage.getItem('refreshToken');
const response = await axios.post('/api/refresh', { refreshToken });
const newAccessToken = response.data.accessToken;
localStorage.setItem('accessToken', newAccessToken);
} catch (error) {
clearInterval(refreshInterval);
console.error('Failed to refresh token:', error);
}
}, 1000 * 60 * 30); // 每 30 分钟刷新一次
}
startTokenRefresh();
-
解释:
- 这个函数使用
setInterval每 30 分钟自动发送一个请求,使用存储的刷新令牌来获取新的访问令牌,并存储在本地存储中。 - 如果刷新失败,清除定时器并记录错误。
- 这个函数使用
1.2 令牌失效时静默刷新
-
在请求失败时刷新令牌:
-
当收到 401 错误时,在后台静默刷新令牌,而不是立即提示用户重新登录或中断用户操作。
-
收起
javascript
axios.interceptors.response.use(
response => response,
async error => {
if (error.response.status === 401) {
try {
const refreshToken = localStorage.getItem('refreshToken');
const response = await axios.post('/api/refresh', { refreshToken });
const newAccessToken = response.data.accessToken;
localStorage.setItem('accessToken', newAccessToken);
error.config.headers['Authorization'] = `Bearer ${newAccessToken}`;
return axios(error.config);
} catch (refreshError) {
console.error('Failed to refresh token:', refreshError);
// 可以显示一个通知或进行其他操作,而不是直接重定向
showNotification('Token expired, please log in again');
}
}
return Promise.reject(error);
}
);
-
解释:
- 收到 401 错误后,尝试使用刷新令牌更新访问令牌,并重新发送原请求。
- 如果刷新失败,不直接重定向用户,而是显示一个通知或采取其他操作。
2. 显示自定义错误信息或模态框
2.1 显示错误消息
-
通知用户认证失败:
-
当收到 401 错误时,显示一个通知或错误消息,而不是直接重定向用户。例如,使用 Vue 组件:
-
收起
vue
<template>
<div>
<button @click="fetchData">Fetch Data</button>
<div v-if="errorMessage" class="error-message">{{ errorMessage }}</div>
</div>
</template>
<script>
import { ref } from 'vue';
import axios from 'axios';
export default {
setup() {
const errorMessage = ref('');
const fetchData = async () => {
try {
const response = await axios.get('/api/protected');
console.log(response.data);
} catch (error) {
if (error.response.status === 401) {
errorMessage.value = 'You do not have permission to access this resource. Please log in or contact support.';
} else {
errorMessage.value = 'An error occurred while fetching data.';
}
}
};
return { errorMessage, fetchData };
}
};
</script>
-
解释:
- 当收到 401 错误时,在页面上显示一个自定义的错误消息,而不是强制用户重新登录。
2.2 使用模态框
-
弹出模态框提示用户:
-
可以使用模态框(如 Vue 的
v-dialog或 Bootstrap 的modal)来提示用户认证问题。
-
收起
vue
<template>
<div>
<button @click="fetchData">Fetch Data</button>
<v-dialog v-model="showModal">
<v-card>
<v-card-title>Authentication Error</v-card-title>
<v-card-text>You do not have permission to access this resource. Please log in or contact support.</v-card-text>
<v-card-actions>
<v-btn @click="showModal = false">Close</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import { ref } from 'vue';
import axios from 'axios';
export default {
setup() {
const showModal = ref(false);
const fetchData = async () => {
try {
const response = await axios.get('/api/protected');
console.log(response.data);
} catch (error) {
if (error.response.status === 401) {
showModal.value = true;
}
}
};
return { showModal, fetchData };
}
};
</script>
-
解释:
- 当收到 401 错误时,弹出一个模态框告知用户认证问题,用户可以关闭模态框而不是必须登录。
3. 降级体验
3.1 部分功能限制
-
限制功能使用:
-
当收到 401 错误时,可以限制用户对某些功能的使用,但不影响其他功能。例如,在一个应用中,用户无法访问高级功能,但可以继续使用基本功能。
-
收起
vue
<template>
<div>
<div v-if="authenticated">
<button @click="accessPremiumFeature">Access Premium Feature</button>
</div>
<div v-else>
<p>You need to authenticate to access premium features.</p>
</div>
<div>
<button @click="accessBasicFeature">Access Basic Feature</button>
</div>
</div>
</template>
<script>
import { ref } from 'vue';
import axios from 'axios';
export default {
setup() {
const authenticated = ref(true);
const accessPremiumFeature = async () => {
try {
await axios.get('/api/premium');
console.log('Premium feature accessed');
} catch (error) {
if (error.response.status === 401) {
authenticated.value = false;
}
}
};
const accessBasicFeature = () => {
console.log('Basic feature accessed');
};
return { authenticated, accessPremiumFeature, accessBasicFeature };
}
};
</script>
-
解释:
- 当用户尝试访问高级功能时收到 401 错误,将
authenticated标记为false,并限制对高级功能的访问,但仍可使用基本功能。
- 当用户尝试访问高级功能时收到 401 错误,将
4. 总结
4.1 令牌刷新
- 可以自动或静默刷新令牌,以保持用户登录状态。
4.2 错误消息和模态框
- 显示自定义错误消息或弹出模态框,通知用户认证问题,而不是强制重新登录。
4.3 降级体验
-
对部分功能进行限制,不影响用户对其他功能的使用。
通过这些方法,可以更灵活地处理服务器返回的 401 错误,提高用户体验,同时确保系统的安全性和可用性。根据不同的应用场景和用户需求,可以选择合适的处理方式。