[未捕获的应用程序错误]:TypeError - 无法读取未定义的属性(读取 'name')
[uncaught application error]: TypeError - Cannot read properties of undefined (reading 'name')
当我尝试使用 Postman 测试 /api/register
端点并遵循 POST
请求时收到此错误消息:
{
"name" : "first",
"email" : "first@one.com",
"password" : "123"
}
[uncaught application error]: TypeError - Cannot read properties of undefined (reading 'name')
request: { url: "http://0.0.0.0:8000/api/register", method: "POST", hasBody: true }
response: { status: 404, type: undefined, hasBody: false, writable: true }
at register (file:///C:/Users/m/app_back/controllers/auth_controller.ts:9:22)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async EventTarget.#handleRequest (https://deno.land/x/oak@v9.0.1/application.ts:379:9)
TypeError: Cannot read properties of undefined (reading 'name')
at register (file:///C:/Users/m/app_back/controllers/auth_controller.ts:9:22)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async EventTarget.#handleRequest (https://deno.land/x/oak@v9.0.1/application.ts:379:9)
这是我的 auth_controller.ts
文件:
import {
create, verify, decode, getNumericDate, RouterContext, hashSync, compareSync
} from "../deps.ts";
import { userCollection } from "../mongo.ts";
import User from "../models/user.ts";
export class AuthController {
async register(ctx: RouterContext) {
const { value: { name, email, password } } = await ctx.request.body().value;
let user = await User.findOne({ email });
if (user) {
ctx.response.status = 422;
ctx.response.body = { message: "Email is already used" };
return;
}
const hashedPassword = hashSync(password);
user = new User({ name, email, password: hashedPassword });
await user.save();
ctx.response.status = 201;
ctx.response.body = {
id: user.id,
name: user.name,
email: user.email
};
}
async login(ctx: RouterContext) {
const { value: { email, password } } = await ctx.request.body().value;
if (!email || !password) {
ctx.response.status = 422;
ctx.response.body = { message: "Please provide email and password" };
return;
}
let user = await User.findOne({ email });
if (!user) {
ctx.response.status = 422;
ctx.response.body = { message: "Incorrect email" };
return;
}
if (!compareSync(password, user.password)) {
ctx.response.status = 422;
ctx.response.body = { message: "Incorrect password" };
return;
}
const key = await crypto.subtle.generateKey(
{ name: "HMAC", hash: "SHA-512" },
true,
["sign", "verify"],
);
const jwt = create( {
alg: "HS256",
typ: "JWT",
}, {
iss: user.email,
exp: getNumericDate(
Date.now() + parseInt(Deno.env.get("JWT_EXP_DURATION") || "0"))
},
key
);
ctx.response.body = {
id: user.id,
name: user.name,
email: user.email,
jwt,
};
}
}
export default new AuthController();
问题是什么,我该如何解决?
编辑:我将这一行添加到代码中:
console.log( await ctx.request.body().value );
这是结果:
{ name: "first", email: "first@one.com", password: "123" }
您遇到此问题是因为您正在尝试访问 ctx.request.body().value.value.name
(请注意多个 value
属性)。您可以将 auth_controller.ts
的第 9 行更改为此以修复它:
const { name, email, password } = await ctx.request.body().value;
附带说明一下,我还注意到您当前的代码还有一些问题。
您的 JWT 算法和生成的密钥加密算法应该匹配
因此,要么将 line 47
上的哈希加密更改为 SHA-256
,要么将 line 53
上的 JWT 算法更改为 HS512
。
您不需要将当前日期传递给 getNumericDate
函数
这个辅助函数已经为您完成了这项工作,您只需在此处传递您希望令牌过期的时间段(以秒为单位)。在你的情况下它将是:
getNumericDate(Deno.env.get("JWT_EXP_DURATION") || 0)}
当我尝试使用 Postman 测试 /api/register
端点并遵循 POST
请求时收到此错误消息:
{
"name" : "first",
"email" : "first@one.com",
"password" : "123"
}
[uncaught application error]: TypeError - Cannot read properties of undefined (reading 'name')
request: { url: "http://0.0.0.0:8000/api/register", method: "POST", hasBody: true }
response: { status: 404, type: undefined, hasBody: false, writable: true }
at register (file:///C:/Users/m/app_back/controllers/auth_controller.ts:9:22)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async EventTarget.#handleRequest (https://deno.land/x/oak@v9.0.1/application.ts:379:9)
TypeError: Cannot read properties of undefined (reading 'name')
at register (file:///C:/Users/m/app_back/controllers/auth_controller.ts:9:22)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async dispatch (https://deno.land/x/oak@v9.0.1/middleware.ts:41:7)
at async EventTarget.#handleRequest (https://deno.land/x/oak@v9.0.1/application.ts:379:9)
这是我的 auth_controller.ts
文件:
import {
create, verify, decode, getNumericDate, RouterContext, hashSync, compareSync
} from "../deps.ts";
import { userCollection } from "../mongo.ts";
import User from "../models/user.ts";
export class AuthController {
async register(ctx: RouterContext) {
const { value: { name, email, password } } = await ctx.request.body().value;
let user = await User.findOne({ email });
if (user) {
ctx.response.status = 422;
ctx.response.body = { message: "Email is already used" };
return;
}
const hashedPassword = hashSync(password);
user = new User({ name, email, password: hashedPassword });
await user.save();
ctx.response.status = 201;
ctx.response.body = {
id: user.id,
name: user.name,
email: user.email
};
}
async login(ctx: RouterContext) {
const { value: { email, password } } = await ctx.request.body().value;
if (!email || !password) {
ctx.response.status = 422;
ctx.response.body = { message: "Please provide email and password" };
return;
}
let user = await User.findOne({ email });
if (!user) {
ctx.response.status = 422;
ctx.response.body = { message: "Incorrect email" };
return;
}
if (!compareSync(password, user.password)) {
ctx.response.status = 422;
ctx.response.body = { message: "Incorrect password" };
return;
}
const key = await crypto.subtle.generateKey(
{ name: "HMAC", hash: "SHA-512" },
true,
["sign", "verify"],
);
const jwt = create( {
alg: "HS256",
typ: "JWT",
}, {
iss: user.email,
exp: getNumericDate(
Date.now() + parseInt(Deno.env.get("JWT_EXP_DURATION") || "0"))
},
key
);
ctx.response.body = {
id: user.id,
name: user.name,
email: user.email,
jwt,
};
}
}
export default new AuthController();
问题是什么,我该如何解决?
编辑:我将这一行添加到代码中:
console.log( await ctx.request.body().value );
这是结果:
{ name: "first", email: "first@one.com", password: "123" }
您遇到此问题是因为您正在尝试访问 ctx.request.body().value.value.name
(请注意多个 value
属性)。您可以将 auth_controller.ts
的第 9 行更改为此以修复它:
const { name, email, password } = await ctx.request.body().value;
附带说明一下,我还注意到您当前的代码还有一些问题。
您的 JWT 算法和生成的密钥加密算法应该匹配
因此,要么将 line 47
上的哈希加密更改为 SHA-256
,要么将 line 53
上的 JWT 算法更改为 HS512
。
您不需要将当前日期传递给 getNumericDate
函数
这个辅助函数已经为您完成了这项工作,您只需在此处传递您希望令牌过期的时间段(以秒为单位)。在你的情况下它将是:
getNumericDate(Deno.env.get("JWT_EXP_DURATION") || 0)}