diff --git a/Api/BaseApiController.cs b/Api/BaseApiController.cs index db21f3b..4e5c6a9 100644 --- a/Api/BaseApiController.cs +++ b/Api/BaseApiController.cs @@ -1,6 +1,9 @@ using Microsoft.AspNetCore.Mvc; using Foxel.Models; using System.Security.Claims; +using System.IdentityModel.Tokens.Jwt; +using Microsoft.IdentityModel.Tokens; +using System.Text; namespace Foxel.Controllers { @@ -14,6 +17,37 @@ namespace Foxel.Controllers return userIdClaim != null ? int.Parse(userIdClaim) : null; } + protected int? GetUserIdFromCookie() + { + try + { + var token = Request.Cookies["token"]; + if (string.IsNullOrEmpty(token)) + { + return null; + } + + var tokenHandler = new JwtSecurityTokenHandler(); + if (!tokenHandler.CanReadToken(token)) + { + return null; + } + + var jwtToken = tokenHandler.ReadJwtToken(token); + var userIdClaim = jwtToken.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value; + if (userIdClaim != null && int.TryParse(userIdClaim, out var userId)) + { + return userId; + } + } + catch (Exception) + { + return null; + } + + return null; + } + protected ActionResult> Success(T data, string message = "操作成功", int statusCode = 200) { return Ok(new BaseResult diff --git a/Api/PictureController.cs b/Api/PictureController.cs index da46de1..954cab7 100644 --- a/Api/PictureController.cs +++ b/Api/PictureController.cs @@ -273,7 +273,7 @@ public class PictureController(IPictureService pictureService, IStorageService s _logger.LogWarning("GetPictureFile: Picture with ID {PictureId} not found.", pictureId); return NotFound("Picture not found."); } - var currentUserId = GetCurrentUserId(); + var currentUserId = GetUserIdFromCookie(); if (picture.Permission != PermissionType.Public) { if (currentUserId == null || picture.UserId != currentUserId.Value) diff --git a/Services/Auth/AuthService.cs b/Services/Auth/AuthService.cs index d3116ae..287ac2b 100644 --- a/Services/Auth/AuthService.cs +++ b/Services/Auth/AuthService.cs @@ -5,7 +5,6 @@ using Foxel.Models.DataBase; using Foxel.Models.Request.Auth; using Foxel.Services.Configuration; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; using static Foxel.Utils.AuthHelper; diff --git a/Web/src/App.tsx b/Web/src/App.tsx index 2bcc9d2..d97c227 100644 --- a/Web/src/App.tsx +++ b/Web/src/App.tsx @@ -43,6 +43,17 @@ const customTheme = { itemHoverColor: '#333333', itemBorderRadius: 8, }, + Table: { + rowSelectedBg: '#f8f9fa', + rowSelectedHoverBg: '#e9ecef', + rowHoverBg: '#fafbfc', + headerBg: '#ffffff', + headerColor: '#495057', + colorBgContainer: '#ffffff', + colorText: '#212529', + colorTextHeading: '#343a40', + borderColor: '#dee2e6', + }, } }; diff --git a/Web/src/api/authApi.ts b/Web/src/api/authApi.ts index 1ca35f5..bdc3cfc 100644 --- a/Web/src/api/authApi.ts +++ b/Web/src/api/authApi.ts @@ -4,6 +4,7 @@ import { type UserRole } from './userManagementApi'; // 认证数据本地存储键 const TOKEN_KEY = 'token'; const USER_KEY = 'user'; +const COOKIE_TOKEN_KEY = 'token'; // 登录请求参数 export interface LoginRequest { @@ -53,6 +54,28 @@ export interface BindAccountRequest { thirdPartyUserId: string; } +// Cookie操作辅助函数 +const setCookie = (name: string, value: string, days: number = 7): void => { + const expires = new Date(); + expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000)); + document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/;SameSite=Lax`; +}; + +const getCookie = (name: string): string | null => { + const nameEQ = name + "="; + const ca = document.cookie.split(';'); + for (let i = 0; i < ca.length; i++) { + let c = ca[i]; + while (c.charAt(0) === ' ') c = c.substring(1, c.length); + if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); + } + return null; +}; + +const deleteCookie = (name: string): void => { + document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/;SameSite=Lax`; +}; + // 用户注册 export async function register(data: RegisterRequest): Promise> { return fetchApi('/auth/register', { @@ -156,6 +179,7 @@ export async function bindAccount(data: BindAccountRequest): Promise { localStorage.setItem(TOKEN_KEY, authData.token); + setCookie(COOKIE_TOKEN_KEY, authData.token, 7); // 保存7天 if (authData.user) { localStorage.setItem(USER_KEY, JSON.stringify(authData.user)); } @@ -165,6 +189,7 @@ export const saveAuthData = (authData: AuthResponse): void => { export const clearAuthData = (): void => { localStorage.removeItem(TOKEN_KEY); localStorage.removeItem(USER_KEY); + deleteCookie(COOKIE_TOKEN_KEY); }; // 检查是否已认证 @@ -186,7 +211,12 @@ export const getStoredUser = (): UserProfile | null => { // 获取存储的令牌 export const getToken = (): string | null => { - return localStorage.getItem(TOKEN_KEY); + // 优先从localStorage获取 + const localToken = localStorage.getItem(TOKEN_KEY); + if (localToken) return localToken; + + // 备用从cookies获取 + return getCookie(COOKIE_TOKEN_KEY); }; // 处理GitHub OAuth回调,接收token并保存