import crypto from 'crypto'; /** * リクエストからセッションIDを生成または取得 * @param request - Next.js Request オブジェクト * @returns セッションID */ export function getSessionId(request: Request): string { // ヘッダーから取得を試みる const headers = request.headers; // x-session-id ヘッダーがあればそれを使用 const sessionIdHeader = headers.get('x-session-id'); if (sessionIdHeader) { console.log('[Session] Using existing session ID from header:', sessionIdHeader); return sessionIdHeader; } // IPアドレスとユーザーエージェントからハッシュを生成 const forwardedFor = headers.get('x-forwarded-for'); const realIp = headers.get('x-real-ip'); const userAgent = headers.get('user-agent') || 'unknown'; const ip = forwardedFor?.split(',')[0] || realIp || 'unknown-ip'; // タイムスタンプを含めて一意性を高める(1時間ごとに変わる) const hourTimestamp = Math.floor(Date.now() / (1000 * 60 * 60)); const sessionString = `${ip}-${userAgent}-${hourTimestamp}`; const sessionId = crypto .createHash('sha256') .update(sessionString) .digest('hex') .substring(0, 16); // 16文字に短縮 console.log('[Session] Generated new session ID:', sessionId, { ip, userAgent }); return sessionId; } /** * クッキーからセッションIDを取得または生成 * @param cookieHeader - Cookie ヘッダー * @returns セッションID */ export function getSessionIdFromCookie(cookieHeader: string | null): string { if (!cookieHeader) { return generateSessionId(); } // セッションIDクッキーを探す const cookies = cookieHeader.split(';').map(c => c.trim()); const sessionCookie = cookies.find(c => c.startsWith('session_id=')); if (sessionCookie) { const sessionId = sessionCookie.split('=')[1]; console.log('[Session] Found session ID in cookie:', sessionId); return sessionId; } return generateSessionId(); } /** * ランダムなセッションIDを生成 * @returns 新しいセッションID */ function generateSessionId(): string { const sessionId = crypto.randomBytes(8).toString('hex'); console.log('[Session] Generated new random session ID:', sessionId); return sessionId; }