typescript 无法在jwt.verify函数中将用户参数过度指定给请求用户

yqyhoc1h  于 2022-11-18  发布在  TypeScript
关注(0)|答案(2)|浏览(69)

我目前正在编写一个jwtVerify. ts。这是我第一次使用TypeScript. Vs-code,它在req.user下面加了下划线,并告诉我该错误:
无法将类型“undefined”分配给类型对象”.ts(2322)。
我现在试着这样检查它:

if(user !== undefined){
           req.user = user;
            }

但它又告诉我:
无法将类型字符串分配给类型“我的用户对象”(2322)。
我尝试在index.d.ts中用any来定义user,但是在所有的jwt函数中都有错误。我尝试在函数中将user定义为对象,但是返回:
没有与此调用匹配的重载。
代码如下:

import * as jwt from 'jsonwebtoken'
import { Request, Response, NextFunction } from 'express';
export const verifyToken = (req:Request, res:Response, next:NextFunction)=>{
    const sec:string = process.env.JWT_SEC as string;
    const authHeader = req.headers.token;
    if(authHeader){
        const token = (authHeader as string).split(' ')[1];
        jwt.verify(token, sec, (err, user)=>{
            if(err){
                res.status(403).json('Token is not valid');
            }
           req.user = user;
            next();
        })
    } else{
        return res.status(401).json('You are not authorized');
    }
};

我有一个@types文件夹,其中包含一个index.d.ts文件,我在其中为Request user全局定义了一个接口:

declare global {
    namespace Express {
        interface Request {
            user:{
                id:string!;
                vorname:string!;
                nachname:string!;
                username:string!;
                email:string!;
                street:string!;
                number:string!;
                plz:number!;
                city:string!;
                password:string!;
                isAdmin:boolean!;
                createdAt: Date!;
                updatedAt: Date!;
            }
        }
    }
}

Request接口工作正常。当我将鼠标悬停在req.user的“user”上时,vs-code向我显示内容。当我将鼠标悬停在函数中的user参数上时,vs-code告诉我它是“string| jwt.JwtPayload |undefined”。那么我如何定义用户,使TypeScript接受这个值呢?如果没有typeScript,这个函数就可以工作。我以前在Mern-Stack考试中用过它。
我加上我的模型,也许这里有什么地方不对:

import mongoose from 'mongoose';

export interface UserDocument extends mongoose.Document{
    vorname:string;
    nachname:string;
    username:string;
    email:string;
    street:string;
    number:string;
    plz:number;
    city:string;
    password:string;
    isAdmin:boolean;
    createdAt: Date;
    updatedAt: Date;
    _doc?: any;
  }
const UserSchema = new mongoose.Schema<UserDocument>({
    vorname:{type:String, required:true},
    nachname:{type:String, required:true},
    username:{type:String, required:true },
    email:{type:String, required:true },
    street:{type:String, required:true },
    number:{type:String, required:true },
    plz:{type:Number, required:true },
    city:{type:String, required:true },
    password:{type:String, required:true },
    isAdmin:{type:Boolean, default:false},
}, 
    {timestamps:true}
)

const User = mongoose.model<UserDocument>('User', UserSchema);

export default User;

我在模型中没有id,因为Mongo会自动设置它。我在界面中有_doc,因为下面的函数:

let sec:string = process.env.JWT_SEC as string;

const accessToken = jwt.sign(
            {id: user!._id,
             isAdmin:user!.isAdmin,
            },
            sec,
            {expiresIn:"30d"}
        )
        const {password, ...others} = user?._doc;
        response.status(200).json({...others, accessToken});

如果接口中没有_doc,它会抛出一个错误。

7xllpg7q

7xllpg7q1#

您需要创建global.d.ts文件,以便在任何对象中显式添加类型。
在根目录下创建global.d.ts文件,在该文件中写入以下代码。

import 'express-serve-static-core'
    
export interface User {
  id:string!;
  vorname:string!;
  nachname:string!;
  username:string!;
  email:string!;
  street:string!;
  number:string!;
  plz:number!;
  city:string!;
  password:string!;
  isAdmin:boolean!;
  createdAt: Date!;
  updatedAt: Date!;
}

declare module 'express' {
  export interface Request {
    user?: User
  }
}

在tsconfig.json文件中执行以下操作

{
   "compilerOptions": {
     // Other options
     "typeRoots": ["./node_modules/@types"]
   },
   "include": ["./**/*.ts"],
   files: ["global.d.ts"]
}

使用Mongoose模型查找用户,然后将其保存在req.user对象中。在您的jwtVerify.ts中执行以下操作

import * as jwt from 'jsonwebtoken'
import { User } from 'usermodelpath'
import { Request, Response, NextFunction } from 'express';

export const verifyToken = (req:Request, res:Response, next:NextFunction)=>{
    const sec:string = process.env.JWT_SEC as string;
    const authHeader = req.headers.token;
    if(authHeader){
        const token = (authHeader as string).split(' ')[1];
        jwt.verify(token, sec, async (err, decoded)=>{
            if(err){
                res.status(403).json('Token is not valid');
            }
           const user = await User.findOne({_id: decoded.id}).lean()
           if(!user) return res.status(400).json({error: 'Not Authorised!' })
           
           req.user = user;
           next();
        })
    } else{
        return res.status(401).json('You are not authorized');
    }
};
eyh26e7m

eyh26e7m2#

好了,我终于写了一些有用的代码。感谢Neeray Kumar,他的回答帮了大忙。这就是代码:

export interface UserDocument extends mongoose.Document{
    vorname:string;
    nachname:string;
    username:string;
    email:string;
    street:string;
    number:string;
    plz:number;
    city:string;
    password:string;
    isAdmin:boolean;
    createdAt: Date;
    updatedAt: Date;
    _doc?: any;
    organization: Types.ObjectId; //This I found in the mongoose documentation. 
  }
const UserSchema = new mongoose.Schema<UserDocument>({
    vorname:{type:String, required:true},
    nachname:{type:String, required:true},
    username:{type:String, required:true },
    email:{type:String, required:true },
    street:{type:String, required:true },
    number:{type:String, required:true },
    plz:{type:Number, required:true },
    city:{type:String, required:true },
    password:{type:String, required:true },
    isAdmin:{type:Boolean, default:false},
    organization: { type: mongoose.Schema.Types.ObjectId, ref: 'Organization' } //organization out of mongoose documentation
}, 
    {timestamps:true}
)

这就是jwt.验证:

export const verifyToken = (req:Request, res:Response, next:NextFunction)=>{
    const sec:string = process.env.JWT_SEC as string;
    const authHeader = req.headers.token;
    console.log(authHeader);
    if(authHeader){
        const token = (authHeader as string).split(' ')[1];
        jwt.verify(token, sec, async (err, user)=>{
            if(err){
                res.status(403).json('Token not valid');
            }
            if(!user) return res.status(400).json({error:"Not authorized"})
            console.log(user, req.user);
            if(user){
               req.user = <any>user; //that is the way to overgive user
            }
            next();
        })
    } else{
        return res.status(401).json('Not authorized');
    }
};

相关问题