node.js - 身份验证中间件 express typescript 错误
问题描述
我使用 express、typescript 和 mongoose 作为后端编程。
以下是以下错误。我在制作作者博客 API 管理系统时得到了这个。在对用户进行身份验证时,我没有得到用户 ID。为什么呢?我在做什么错误。如何以另一种方式存储用户 ID 以进行身份验证?
错误:
TypeError: Cannot read property '_id' of undefined
at PostsController.createPost
用户界面.ts
interface User {
_id: string;
name: string;
email: string;
password: string;
}
export default User;
auth.middle.ts
import { NextFunction, Response,Request } from 'express';
import * as jwt from 'jsonwebtoken';
import AuthenticationTokenMissingException from '../exceptions/AuthenticationTokenMissingException';
import WrongAuthenticationTokenException from '../exceptions/WrongAuthenticationTokenException';
import DataStoredInToken from '../interfaces/dataStoredInToken';
import RequestWithUser from '../interfaces/requestWithUser.interface';
import userModel from '../users/user.model';
import User from 'users/user.interface';
async function authMiddleware(request: RequestWithUser,req:Request, response: Response, next: NextFunction) {
const cookies = req.cookies;
if (cookies && cookies.Authorization) {
const secret = process.env.JWT_SECRET;
try {
const verificationResponse = jwt.verify(cookies.Authorization, secret) as DataStoredInToken;
const id = verificationResponse._id;
const user = await userModel.findById(id);
if (user) {
request.user = user;
//something wrong is here,I guess ?????
next();
} else {
next(new WrongAuthenticationTokenException());
}
} catch (error) {
next(new WrongAuthenticationTokenException());
}
} else {
next(new AuthenticationTokenMissingException());
}
}
export default authMiddleware;
身份验证.controller.ts
import * as bcrypt from 'bcrypt';
import * as express from 'express';
import * as jwt from 'jsonwebtoken';
import User from 'users/user.interface';
import UserWithThatEmailAlreadyExistsException from '../exceptions/UserWithThatEmailAlreadyExistsException';
import WrongCredentialsException from '../exceptions/WrongCredentialsException';
import Controller from '../interfaces/controller.interface';
import DataStoredInToken from '../interfaces/dataStoredInToken';
import TokenData from '../interfaces/tokenData.interface';
import validationMiddleware from '../middleware/validation.middleware';
import CreateUserDto from '../users/user.dto';
import userModel from './../users/user.model';
import LogInDto from './logIn.dto';
class AuthenticationController implements Controller {
public path = '/auth';
public router = express.Router();
private user = userModel;
constructor() {
this.initializeRoutes();
}
private initializeRoutes() {
this.router.post(`${this.path}/register`, validationMiddleware(CreateUserDto), this.registration);
this.router.post(`${this.path}/login`, validationMiddleware(LogInDto), this.loggingIn);
this.router.post(`${this.path}/logout`, this.loggingOut);
}
private registration = async (request: express.Request, response: express.Response, next: express.NextFunction) => {
const userData: CreateUserDto = request.body;
if (
await this.user.findOne({ email: userData.email })
) {
next(new UserWithThatEmailAlreadyExistsException(userData.email));
} else {
const hashedPassword = await bcrypt.hash(userData.password, 10);
const user = await this.user.create({
...userData,
password: hashedPassword,
});
user.password = undefined;
const tokenData = this.createToken(user);
response.setHeader('Set-Cookie', [this.createCookie(tokenData)]);
response.send(user);
}
}
private loggingIn = async (request: express.Request, response: express.Response, next: express.NextFunction) => {
const logInData: LogInDto = request.body;
const user = await this.user.findOne({ email: logInData.email });
if (user) {
const isPasswordMatching = await bcrypt.compare(logInData.password, user.password);
if (isPasswordMatching) {
user.password = undefined;
const tokenData = this.createToken(user);
response.setHeader('Set-Cookie', [this.createCookie(tokenData)]);
response.send(user);
} else {
next(new WrongCredentialsException());
}
} else {
next(new WrongCredentialsException());
}
}
private loggingOut = (request: express.Request, response: express.Response) => {
response.setHeader('Set-Cookie', ['Authorization=;Max-age=0']);
response.sendStatus(200);
}
private createCookie(tokenData: TokenData) {
return `Authorization=${tokenData.token}; HttpOnly; Max-Age=${tokenData.expiresIn}`;
}
private createToken(user: User): TokenData {
const expiresIn = 60 * 60; // an hour
const secret = process.env.JWT_SECRET;
const dataStoredInToken: DataStoredInToken = {
_id: user._id,
};
return {
expiresIn,
token: jwt.sign(dataStoredInToken, secret, { expiresIn }),
};
}
}
export default AuthenticationController;
~~~
**posts.controller.ts**
~~~
import * as express from 'express';
import PostNotFoundException from '../exceptions/PostNotFoundException';
import Controller from '../interfaces/controller.interface';
import RequestWithUser from '../interfaces/requestWithUser.interface';
import authMiddleware from '../middleware/auth.middleware';
import validationMiddleware from '../middleware/validation.middleware';
import CreatePostDto from './post.dto';
import Post from './post.interface';
import postModel from './posts.model';
class PostsController implements Controller {
public path = '/posts';
public router = express.Router();
private post = postModel;
constructor() {
this.initializeRoutes();
}
private initializeRoutes() {
this.router.get(this.path, this.getAllPosts);
this.router.get(`${this.path}/:id`, this.getPostById);
this.router
.all(`${this.path}/*`, authMiddleware)
.patch(`${this.path}/:id`, validationMiddleware(CreatePostDto, true), this.modifyPost)
.delete(`${this.path}/:id`, this.deletePost)
.post(this.path, authMiddleware, validationMiddleware(CreatePostDto), this.createPost);
}
private getAllPosts = async (request: express.Request, response: express.Response) => {
const posts = await this.post.find();
response.send(posts);
}
private getPostById = async (request: express.Request, response: express.Response, next: express.NextFunction) => {
const id = request.params.id;
const post = await this.post.findById(id);
if (post) {
response.send(post);
} else {
next(new PostNotFoundException(id));
}
}
private modifyPost = async (request: express.Request, response: express.Response, next: express.NextFunction) => {
const id = request.params.id;
const postData: Post = request.body;
const post = await this.post.findByIdAndUpdate(id, postData, { new: true });
if (post) {
response.send(post);
} else {
next(new PostNotFoundException(id));
}
}
private createPost = async (request: RequestWithUser, response: express.Response) => {
const postData: CreatePostDto = request.body;
const createdPost = new this.post({
...postData,
authorId: request.user._id,
});
const savedPost = await createdPost.save();
response.send(savedPost);
}
private deletePost = async (request: express.Request, response: express.Response, next: express.NextFunction) => {
const id = request.params.id;
const successResponse = await this.post.findByIdAndDelete(id);
if (successResponse) {
response.send(200);
} else {
next(new PostNotFoundException(id));
}
}
}
export default PostsController;
~~~
解决方案
推荐阅读
- doctrine-orm - 无法在 Symfony 4.1 项目中安装 Doctrine Migrations V2
- indexing - 基于 4 级指数的 DAX 移动平均线
- azure-devops - 如何从 VSTS 构建中排除某些目录?
- android - 将 GeoFire 查询加载到 RecyclerView 时应用程序崩溃
- batch-file - Windows BAT 文件 SET 命令以奇怪的方式工作 - Python 虚拟环境激活脚本
- c# - 通过表单创建全局变量
- javascript - 如何通过单击使用 redux 的按钮打开我的模式?
- firebase - 包含一些敏感数据的公共/可共享路由的最佳设计模式
- c# - 为行星设置重力时出现 Unity/C# 错误
- excel - 使用 vba 的 Excel TOC - 删除了前导零