我是平均堆栈开发的初学者,我正在尝试在 Postman 中运行“api/users/login”,它显示“用户名或密码无效!”。当我运行“注册/用户/注册”时,我得到“用户已经存在”。我该如何解决。
注册:
登录:
这是我的代码:
用户.router.ts
import {Router} from 'express';
import { sample_users } from '../data';
import jwt from 'jsonwebtoken';
import asyncHandler from 'express-async-handler';
import { User, UserModel } from '../models/user.model';
import { HTTP_BAD_REQUEST } from '../constants/http_status';
import bcrypt from 'bcryptjs';
const router = Router();
router.get("/seed", asyncHandler(
async (req, res) => {
const usersCount = await UserModel.countDocuments();
if(usersCount> 0){
res.send("Seed is already done!");
return;
}
await UserModel.create(sample_users);
res.send("Seed Is Done!");
}
))
router.post("/login", asyncHandler(
async (req, res) => {
const {email, password} = await req.body;
console.log(req.body.email + " userEmail");
console.log(req.body.password + " userPassword" );
const user = await UserModel.findOne({email});
console.log(user?.password);
if(user && (await bcrypt.compare(password,user.password))) {
res.send(generateTokenReponse(user));
}
else{
res.status(HTTP_BAD_REQUEST).send("Username or password is invalid!");
}
}
))
router.post('/register', asyncHandler(
async (req, res) => {
const {name, email, password, address} = await req.body;
const user = await UserModel.findOne({email});
if(user){
res.status(HTTP_BAD_REQUEST)
.send('User is already exist, please login!');
return;
}
const encryptedPassword = await bcrypt.hash(password, 10);
const newUser:User = {
id:'',
name,
email: email.toLowerCase(),
password: encryptedPassword,
address,
isAdmin: false
}
const dbUser = await UserModel.create(newUser);
res.send(generateTokenReponse(dbUser));
}
))
const generateTokenReponse = (user : User) => {
const token = jwt.sign({
id: user.id, email:user.email, isAdmin: user.isAdmin
},process.env.JWT_SECRET!,{
expiresIn:"30d"
});
return {
id: user.id,
email: user.email,
name: user.name,
address: user.address,
isAdmin: user.isAdmin,
token: token
};
}
export default router;
用户.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
import { BehaviorSubject, Observable, tap } from 'rxjs';
import { USER_LOGIN_URL, USER_REGISTER_URL } from '../shared/constants/urls';
import { IUserLogin } from '../shared/interfaces/IUserLogin';
import { IUserRegister } from '../shared/interfaces/IUserRegister';
import { User } from '../shared/models/User';
const USER_KEY = 'User';
@Injectable({
providedIn: 'root'
})
export class UserService {
private userSubject =
new BehaviorSubject<User>(this.getUserFromLocalStorage());
public userObservable:Observable<User>;
constructor(private http:HttpClient, private toastrService:ToastrService) {
this.userObservable = this.userSubject.asObservable();
}
public get currentUser():User{
return this.userSubject.value;
}
login(userLogin:IUserLogin):Observable<User>{
return this.http.post<User>(USER_LOGIN_URL, userLogin).pipe(
tap({
next: (user) =>{
this.setUserToLocalStorage(user);
this.userSubject.next(user);
this.toastrService.success(
`Welcome to Foodmine ${user.name}!`,
'Login Successful'
)
},
error: (errorResponse) => {
this.toastrService.error(errorResponse.error, 'Login Failed');
}
})
);
}
register(userRegiser:IUserRegister): Observable<User>{
return this.http.post<User>(USER_REGISTER_URL, userRegiser).pipe(
tap({
next: (user) => {
this.setUserToLocalStorage(user);
this.userSubject.next(user);
this.toastrService.success(
`Welcome to the Foodmine ${user.name}`,
'Register Successful'
)
},
error: (errorResponse) => {
this.toastrService.error(errorResponse.error,
'Register Failed')
}
})
)
}
logout(){
this.userSubject.next(new User());
localStorage.removeItem(USER_KEY);
window.location.reload();
}
private setUserToLocalStorage(user:User){
localStorage.setItem(USER_KEY, JSON.stringify(user));
}
private getUserFromLocalStorage():User{
const userJson = localStorage.getItem(USER_KEY);
if(userJson) return JSON.parse(userJson) as User;
return new User();
}
}
登录.component.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { UserService } from 'src/app/services/user.service';
@Component({
selector: 'app-login-page',
templateUrl: './login-page.component.html',
styleUrls: ['./login-page.component.css']
})
export class LoginPageComponent implements OnInit {
loginForm!:FormGroup;
isSubmitted = false;
returnUrl = '';
constructor(private formBuilder: FormBuilder
, private userService:UserService,
private activatedRoute:ActivatedRoute,
private router:Router) { }
ngOnInit(): void {
this.loginForm = this.formBuilder.group({
email:['', [Validators.required,Validators.email]],
password:['', Validators.required]
});
this.returnUrl = this.activatedRoute.snapshot.queryParams.returnUrl;
}
get fc(){
return this.loginForm.controls;
}
submit(){
this.isSubmitted = true;
if(this.loginForm.invalid) return;
this.userService.login({email:this.fc.email.value,
password: this.fc.password.value}).subscribe(() => {
this.router.navigateByUrl(this.returnUrl);
});
}
}
auth.guard.ts
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { UserService } from 'src/app/services/user.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private userService:UserService, private router:Router){
}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if(this.userService.currentUser.token) return true;
this.router.navigate(['/login'], {queryParams:{returnUrl: state.url}})
return false;
}
}
我遇到了同样的问题,但事实证明我的代码没有任何问题。我只需在 Postman 中将 Body 切换为 x-www-form-urlencoded 即可。