用户变动撤销所有刷新token,立即失效accesstoken
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import type { AuthInfo } from './auth';
|
||||
|
||||
const userInvalidBefore = new Map<string, number>();
|
||||
const deviceInvalidBefore = new Map<string, number>();
|
||||
|
||||
function makeDeviceKey(username: string, tokenId: string): string {
|
||||
return `${username}:${tokenId}`;
|
||||
}
|
||||
|
||||
export function invalidateUserAccessTokens(username: string, invalidatedAt = Date.now()): void {
|
||||
const current = userInvalidBefore.get(username) || 0;
|
||||
if (invalidatedAt > current) {
|
||||
userInvalidBefore.set(username, invalidatedAt);
|
||||
}
|
||||
}
|
||||
|
||||
export function invalidateDeviceAccessToken(
|
||||
username: string,
|
||||
tokenId: string,
|
||||
invalidatedAt = Date.now()
|
||||
): void {
|
||||
const key = makeDeviceKey(username, tokenId);
|
||||
const current = deviceInvalidBefore.get(key) || 0;
|
||||
if (invalidatedAt > current) {
|
||||
deviceInvalidBefore.set(key, invalidatedAt);
|
||||
}
|
||||
}
|
||||
|
||||
export function isAccessTokenInvalidated(authInfo: AuthInfo | null): boolean {
|
||||
if (!authInfo?.username || !authInfo.timestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const userInvalidatedAt = userInvalidBefore.get(authInfo.username);
|
||||
if (userInvalidatedAt && authInfo.timestamp <= userInvalidatedAt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (authInfo.tokenId) {
|
||||
const deviceInvalidatedAt = deviceInvalidBefore.get(
|
||||
makeDeviceKey(authInfo.username, authInfo.tokenId)
|
||||
);
|
||||
if (deviceInvalidatedAt && authInfo.timestamp <= deviceInvalidatedAt) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getAccessTokenInvalidationState() {
|
||||
return {
|
||||
userInvalidBefore,
|
||||
deviceInvalidBefore,
|
||||
};
|
||||
}
|
||||
+5
-2
@@ -1,5 +1,7 @@
|
||||
import { NextRequest } from 'next/server';
|
||||
|
||||
import { isAccessTokenInvalidated } from './access-token-invalidation';
|
||||
|
||||
export type AuthInfo = {
|
||||
password?: string;
|
||||
username?: string;
|
||||
@@ -65,7 +67,7 @@ export function getAuthInfoFromCookie(request: NextRequest): AuthInfo | null {
|
||||
const headerValue = getAuthTokenFromHeader(authHeader);
|
||||
const headerAuthInfo = parseAuthInfo(headerValue);
|
||||
if (headerAuthInfo) {
|
||||
return headerAuthInfo;
|
||||
return isAccessTokenInvalidated(headerAuthInfo) ? null : headerAuthInfo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +77,8 @@ export function getAuthInfoFromCookie(request: NextRequest): AuthInfo | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parseAuthInfo(authCookie.value);
|
||||
const authInfo = parseAuthInfo(authCookie.value);
|
||||
return isAccessTokenInvalidated(authInfo) ? null : authInfo;
|
||||
}
|
||||
|
||||
// 从cookie获取认证信息 (客户端使用)
|
||||
|
||||
Reference in New Issue
Block a user