何时刷新 JWT 令牌?
When to refresh a JWT token?
目前我在 Laravel 后端使用 JWT-Auth 来使用令牌保护我的 API 路由。但是,一段时间后,令牌变得无效,我收到错误 401 Unauthorized
。所以我想我必须在某处刷新令牌。什么时候做这件事最好?每次您提出请求时,我都会读到有关这样做的信息,但我想确保这是正确的做法。我使用了他们文档中的指南:https://jwt-auth.readthedocs.io/en/develop/quick-start/#create-the-authcontroller。在这里,他们创建了一个函数来刷新令牌。但是我每次发出请求时如何实现呢?我只是在控制器中使用 Axios
请求调用此函数,还是在另一个控制器或其他东西中调用它?非常感谢任何提示。
顺便说一句,我有一个Vue.js前端。
Tymon/JWTAuth 你有两个选择:
- 您可以将
jwt.refresh
中间件添加到您的 api 路由,这将在每次发出请求时刷新令牌。此解决方案的缺点是可能会被滥用。好处是您真的不需要担心应用程序中的令牌,特别是如果您没有前端或不自己开发前端。
- 您解析令牌客户端。 jwt 令牌的前两部分完全 public 并且是 base64 编码的。您真的不需要知道此令牌是否由服务器 client-side 签名,因此您可以安全地忽略最后一部分。如果您有一个围绕 api 调用的包装器来处理 api 调用的通用逻辑(例如,添加授权 header 开始),则此解决方案相对容易。
const token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJpYXQiOjE1NTUzNDkxMjYsImV4cCI6MTU1NTM3NzkyNiwibmJmIjoxNTU1MzQ5MTI2LCJqdGkiOiJtZEdTNGE2ZDJnNHM5NzRnNSJ9.TygbG5smlhAapE8fy4rgXlLVYW-qOcWtLYnnbgJCIKg";
function shouldRefreshToken(token) {
const currentTime = 1555350309829; // Date.now()
const universalTimestamp = currentTime / 1000;
const gracePeriod = 60 * 60 * 8; // 8 hours
const tokenParts = token.split('.');
const payload = JSON.parse(atob(tokenParts[1]));
if (payload.iat > universalTimestamp) {
console.log("This monstrosity was issued in the future O_o");
}
if (payload.nbf > universalTimestamp) {
console.log("This token is not valid yet. Refreshing it does not yield anything useful. Maybe we still have some previous token?");
}
if (payload.exp < universalTimestamp) {
console.log("This token has expired. We should try to refresh it before doing anything else.");
} else if (payload.exp - gracePeriod < universalTimestamp) {
console.log("This token is about to expire. We can refresh it asynchronously.");
} else {
console.log("Nah, we are fine!");
}
}
shouldRefreshToken(token);
最后,您可能希望将请求发送到执行类似操作的刷新端点,然后由前端进行解析:
$myNewToken = JWTAuth::refresh(JWTAuth::getToken());
response()->header('Authorization', "Bearer {$myNewToken}");
要使其正常工作,您可以执行以下操作:
import store from '../store';
import { shouldRefreshToken } from '../helpers/auth';
const someBaseUrl = 'https://example.com';
export function request(options = {}) {
// Hopefully you rewrite that function above to return a boolean ;-)
if (shouldRefreshToken(store.state.auth.token)) {
refreshToken();
}
const config = {
method: options.method,
url: `${someBaseUrl}/${options.resource}`,
credentials: 'include',
headers: {
...(options.headers || {}),
Authorization: `Bearer ${store.state.auth.token}`,
'Content-Type': 'application/json'
},
data: options.data
}
return axios(config).then(parseResponse)
}
function parseResponse(axiosResponse) {
// Probably want to get the token and do something with it
}
function refreshToken() {
axios({
method: 'POST',
url: `${someBaseUrl}/refresh`
}).then(parseResponse)
}
目前我在 Laravel 后端使用 JWT-Auth 来使用令牌保护我的 API 路由。但是,一段时间后,令牌变得无效,我收到错误 401 Unauthorized
。所以我想我必须在某处刷新令牌。什么时候做这件事最好?每次您提出请求时,我都会读到有关这样做的信息,但我想确保这是正确的做法。我使用了他们文档中的指南:https://jwt-auth.readthedocs.io/en/develop/quick-start/#create-the-authcontroller。在这里,他们创建了一个函数来刷新令牌。但是我每次发出请求时如何实现呢?我只是在控制器中使用 Axios
请求调用此函数,还是在另一个控制器或其他东西中调用它?非常感谢任何提示。
顺便说一句,我有一个Vue.js前端。
Tymon/JWTAuth 你有两个选择:
- 您可以将
jwt.refresh
中间件添加到您的 api 路由,这将在每次发出请求时刷新令牌。此解决方案的缺点是可能会被滥用。好处是您真的不需要担心应用程序中的令牌,特别是如果您没有前端或不自己开发前端。 - 您解析令牌客户端。 jwt 令牌的前两部分完全 public 并且是 base64 编码的。您真的不需要知道此令牌是否由服务器 client-side 签名,因此您可以安全地忽略最后一部分。如果您有一个围绕 api 调用的包装器来处理 api 调用的通用逻辑(例如,添加授权 header 开始),则此解决方案相对容易。
const token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJpYXQiOjE1NTUzNDkxMjYsImV4cCI6MTU1NTM3NzkyNiwibmJmIjoxNTU1MzQ5MTI2LCJqdGkiOiJtZEdTNGE2ZDJnNHM5NzRnNSJ9.TygbG5smlhAapE8fy4rgXlLVYW-qOcWtLYnnbgJCIKg";
function shouldRefreshToken(token) {
const currentTime = 1555350309829; // Date.now()
const universalTimestamp = currentTime / 1000;
const gracePeriod = 60 * 60 * 8; // 8 hours
const tokenParts = token.split('.');
const payload = JSON.parse(atob(tokenParts[1]));
if (payload.iat > universalTimestamp) {
console.log("This monstrosity was issued in the future O_o");
}
if (payload.nbf > universalTimestamp) {
console.log("This token is not valid yet. Refreshing it does not yield anything useful. Maybe we still have some previous token?");
}
if (payload.exp < universalTimestamp) {
console.log("This token has expired. We should try to refresh it before doing anything else.");
} else if (payload.exp - gracePeriod < universalTimestamp) {
console.log("This token is about to expire. We can refresh it asynchronously.");
} else {
console.log("Nah, we are fine!");
}
}
shouldRefreshToken(token);
最后,您可能希望将请求发送到执行类似操作的刷新端点,然后由前端进行解析:
$myNewToken = JWTAuth::refresh(JWTAuth::getToken());
response()->header('Authorization', "Bearer {$myNewToken}");
要使其正常工作,您可以执行以下操作:
import store from '../store';
import { shouldRefreshToken } from '../helpers/auth';
const someBaseUrl = 'https://example.com';
export function request(options = {}) {
// Hopefully you rewrite that function above to return a boolean ;-)
if (shouldRefreshToken(store.state.auth.token)) {
refreshToken();
}
const config = {
method: options.method,
url: `${someBaseUrl}/${options.resource}`,
credentials: 'include',
headers: {
...(options.headers || {}),
Authorization: `Bearer ${store.state.auth.token}`,
'Content-Type': 'application/json'
},
data: options.data
}
return axios(config).then(parseResponse)
}
function parseResponse(axiosResponse) {
// Probably want to get the token and do something with it
}
function refreshToken() {
axios({
method: 'POST',
url: `${someBaseUrl}/refresh`
}).then(parseResponse)
}