feat: 去除basic auth认证,添加登录和登出 API,更新中间件以支持 cookie 验证
This commit is contained in:
+83
@@ -0,0 +1,83 @@
|
||||
import { config } from './config'
|
||||
|
||||
export const AUTH_COOKIE_NAME = 'auth_token'
|
||||
const SECRET_KEY = config.auth.secret
|
||||
|
||||
// Helper to generate a random nonce
|
||||
function generateNonce() {
|
||||
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
|
||||
}
|
||||
|
||||
// Helper to create a signed token (simplified JWT-like structure)
|
||||
export async function createToken(username: string) {
|
||||
const header = { alg: 'HS256', typ: 'JWT' }
|
||||
const payload = {
|
||||
sub: username,
|
||||
iat: Date.now(),
|
||||
exp: Date.now() + 24 * 60 * 60 * 1000, // 24 hours
|
||||
nonce: generateNonce() // Ensure token is different every time
|
||||
}
|
||||
|
||||
const encodedHeader = btoa(JSON.stringify(header))
|
||||
const encodedPayload = btoa(JSON.stringify(payload))
|
||||
const data = `${encodedHeader}.${encodedPayload}`
|
||||
|
||||
const key = await crypto.subtle.importKey(
|
||||
'raw',
|
||||
new TextEncoder().encode(SECRET_KEY),
|
||||
{ name: 'HMAC', hash: 'SHA-256' },
|
||||
false,
|
||||
['sign']
|
||||
)
|
||||
|
||||
const signature = await crypto.subtle.sign(
|
||||
'HMAC',
|
||||
key,
|
||||
new TextEncoder().encode(data)
|
||||
)
|
||||
|
||||
// Convert signature to base64
|
||||
const signatureArray = Array.from(new Uint8Array(signature))
|
||||
const encodedSignature = btoa(String.fromCharCode.apply(null, signatureArray))
|
||||
|
||||
return `${data}.${encodedSignature}`
|
||||
}
|
||||
|
||||
// Helper to verify token
|
||||
export async function verifyToken(token: string) {
|
||||
try {
|
||||
const parts = token.split('.')
|
||||
if (parts.length !== 3) return false
|
||||
|
||||
const [encodedHeader, encodedPayload, encodedSignature] = parts
|
||||
const data = `${encodedHeader}.${encodedPayload}`
|
||||
|
||||
const key = await crypto.subtle.importKey(
|
||||
'raw',
|
||||
new TextEncoder().encode(SECRET_KEY),
|
||||
{ name: 'HMAC', hash: 'SHA-256' },
|
||||
false,
|
||||
['verify']
|
||||
)
|
||||
|
||||
const signature = new Uint8Array(
|
||||
atob(encodedSignature).split('').map(c => c.charCodeAt(0))
|
||||
)
|
||||
|
||||
const isValid = await crypto.subtle.verify(
|
||||
'HMAC',
|
||||
key,
|
||||
signature,
|
||||
new TextEncoder().encode(data)
|
||||
)
|
||||
|
||||
if (!isValid) return false
|
||||
|
||||
const payload = JSON.parse(atob(encodedPayload))
|
||||
if (payload.exp < Date.now()) return false
|
||||
|
||||
return true
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user