feat(server): 添加用户信息获取逻辑
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.11.0",
|
||||
"compression": "^1.7.5",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.21.2",
|
||||
@@ -21,6 +22,7 @@
|
||||
"sqlite3": "^5.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/axios": "^0.9.36",
|
||||
"@types/compression": "^1.7.5",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.13",
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Express } from "express";
|
||||
import {userInfoMiddleware} from "@/middleware/auth";
|
||||
|
||||
export const createApis = (app: Express) => {
|
||||
app.get("/api/test", async (req, res) => {
|
||||
app.get("/api/test", userInfoMiddleware, async (req, res) => {
|
||||
console.log(req.userInfo);
|
||||
res.status(200).json({
|
||||
message: "success",
|
||||
data: null,
|
||||
|
||||
134
packages/server/src/middleware/auth.ts
Normal file
134
packages/server/src/middleware/auth.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import axios from "axios";
|
||||
|
||||
export type UserInfo = {
|
||||
userId: number;
|
||||
nickname: string;
|
||||
avatarUrl: string;
|
||||
gender: 'MALE' |'FEMALE' | 'UNKNOWN';
|
||||
nimToken: string; // NetEase Cloud Communication token
|
||||
nimAccountId: string; // NetEase Cloud Communication account ID
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
// Extend Express Request type to add user information
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Request {
|
||||
userInfo?: UserInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract Bearer token from request header
|
||||
*/
|
||||
export const extractTokenFromHeader = (authHeader: string | undefined): string | null => {
|
||||
if (!authHeader) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parts = authHeader.split(" ");
|
||||
if (parts.length !== 2 || parts[0] !== "Bearer") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parts[1];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get user information by token
|
||||
*/
|
||||
export const getUserInfoByToken = async (token: string): Promise<any> => {
|
||||
try {
|
||||
const response = await axios.post(
|
||||
"https://egret.byteawake.com/api/user/info",
|
||||
{}, // 请求体数据,这里为空对象
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
timeout: 10000, // 10 second timeout
|
||||
}
|
||||
);
|
||||
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
if (error.response) {
|
||||
// API returned error response
|
||||
throw new Error(`Failed to get user information: ${error.response.status} ${error.response.statusText}`);
|
||||
} else if (error.request) {
|
||||
// Request was sent but no response received
|
||||
throw new Error("Failed to get user information: timeout or network error");
|
||||
} else {
|
||||
// Other errors
|
||||
throw new Error(`Failed to get user information: ${error.message}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* User information middleware
|
||||
* Automatically extract token from request header and get user information, store result in req.userInfo
|
||||
*/
|
||||
export const userInfoMiddleware = async (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<void> => {
|
||||
try {
|
||||
const authHeader = req.headers.authorization;
|
||||
const token = extractTokenFromHeader(authHeader);
|
||||
|
||||
if (!token) {
|
||||
res.status(401).json({
|
||||
error: "No valid access token provided",
|
||||
message: "Missing Bearer token in Authorization header",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Get user information
|
||||
const userInfo = await getUserInfoByToken(token);
|
||||
req.userInfo = userInfo;
|
||||
|
||||
next();
|
||||
} catch (error: any) {
|
||||
res.status(401).json({
|
||||
error: "User authentication failed",
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Optional user information middleware
|
||||
* If there is a token, get user information; if there is no token, the request will not be blocked
|
||||
*/
|
||||
export const optionalUserInfoMiddleware = async (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<void> => {
|
||||
try {
|
||||
const authHeader = req.headers.authorization;
|
||||
const token = extractTokenFromHeader(authHeader);
|
||||
|
||||
if (token) {
|
||||
try {
|
||||
const userInfo = await getUserInfoByToken(token);
|
||||
req.userInfo = userInfo;
|
||||
} catch (error) {
|
||||
// If getting user information fails, do not block the request from continuing, but do not set userInfo
|
||||
console.warn("Failed to get user information:", error);
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
} catch (error) {
|
||||
// If the middleware itself encounters an error, do not block the request from continuing
|
||||
console.error("User information middleware error:", error);
|
||||
next();
|
||||
}
|
||||
};
|
||||
50
packages/server/src/services/userService.ts
Normal file
50
packages/server/src/services/userService.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Request } from "express";
|
||||
import {extractTokenFromHeader, getUserInfoByToken, UserInfo} from "../middleware/auth";
|
||||
|
||||
/**
|
||||
* User information service class
|
||||
* Provides user information retrieval methods for direct use in business logic
|
||||
*/
|
||||
export class UserService {
|
||||
/**
|
||||
* Get user information from request
|
||||
* If userInfo already exists in request (set by middleware), return it directly
|
||||
* Otherwise extract token from request header and get user information
|
||||
*/
|
||||
static async getUserInfoFromRequest(req: Request): Promise<UserInfo> {
|
||||
// If middleware has already set user information, return it directly
|
||||
if (req.userInfo) {
|
||||
return req.userInfo;
|
||||
}
|
||||
|
||||
// Extract token from request header
|
||||
const token = extractTokenFromHeader(req.headers.authorization);
|
||||
if (!token) {
|
||||
throw new Error("No valid access token found");
|
||||
}
|
||||
|
||||
// Get user information
|
||||
return await getUserInfoByToken(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if user is logged in
|
||||
*/
|
||||
static isUserLoggedIn(req: Request): boolean {
|
||||
return !!req.userInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user ID (assuming user info contains id field)
|
||||
*/
|
||||
static getUserId(req: Request): string | number | null {
|
||||
return req.userInfo?.userId || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user information directly by token (not dependent on request object)
|
||||
*/
|
||||
static async getUserInfoByToken(token: string): Promise<any> {
|
||||
return await getUserInfoByToken(token);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user