mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-05-12 11:32:56 +08:00
feat(auth): implement cookie-based token management and update user ID retrieval
This commit is contained in:
@@ -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<BaseResult<T>> Success<T>(T data, string message = "操作成功", int statusCode = 200)
|
||||
{
|
||||
return Ok(new BaseResult<T>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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<BaseResult<AuthResponse>> {
|
||||
return fetchApi<AuthResponse>('/auth/register', {
|
||||
@@ -156,6 +179,7 @@ export async function bindAccount(data: BindAccountRequest): Promise<BaseResult<
|
||||
// 保存认证数据到本地存储
|
||||
export const saveAuthData = (authData: AuthResponse): void => {
|
||||
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并保存
|
||||
|
||||
Reference in New Issue
Block a user