Angular+(Node/express).js 首次登录失败,刷新页面强制用户注销
Login fails for the first time login and refreshing page forces user to logout in Angular+(Node/express).js
当我第一次尝试登录时,它确实对用户进行了身份验证,并将 AuthService 中的 loggedInStatus 设置为 true,但 AuthGuard 中的 loggedIn 设置为 false,因此不允许导航到仪表板。还有 console.logs 是乱序的,即首先记录 GUARD,然后记录 LOGGEDINSTATUS,而它应该与此相反。在我第二次尝试成功登录并导航到仪表板后,在重新加载页面时,它会将我重定向到登录页面,并且 AuthGaurd 中 loggedIn 的值未定义。
登录组件 Typescript
import { Component, OnInit } from '@angular/core';
import { FormGroup, Validators, FormBuilder, NgForm } from '@angular/forms';
import { Router } from '@angular/router';
import { Credentials } from '../Services/models';
import { AuthService } from '../Services/auth/auth.service';
import * as util from '../../../Server/Utilities/util';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
hide = true;
constructor(
private authService: AuthService,
private formBuilder: FormBuilder,
private router: Router
) {
this.loginForm = this.formBuilder.group({
email: ['', [Validators.required, Validators.email]],
pass: ['', [Validators.required, Validators.minLength(6)]]
});
}
ngOnInit() {
}
auth(form: NgForm){
event.preventDefault();
event.stopPropagation();
let creds: Credentials = {
email: this.loginForm.controls.email.value,
password: this.loginForm.controls.pass.value
}
this.authService.authenticateUser(creds).subscribe((data: any) => {
if(data.statusCode == util.statusCode.OK) {
form.resetForm();
this.router.navigate(['dashboard']);
}
else{
console.log("resp", data);
}
});
}
}
授权服务
import { Response, Headers, URLSearchParams, RequestOptions } from '@angular/http';
import { Observable, throwError } from 'rxjs';
import { map, catchError, shareReplay } from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { User, Credentials } from '../models';
@Injectable({
providedIn: 'root'
})
export class AuthService {
baseUrl = 'http://localhost:3000';
private loggedInStatus: boolean;
constructor( private http: HttpClient ) {
this.getIsLoggedIn();
}
get loggedIn() : boolean {
this.getIsLoggedIn();
return this.loggedInStatus;
}
getIsLoggedIn() {
this.http.get(this.baseUrl + '/login', {
withCredentials: true
}).subscribe((res: any) => {
this.loggedInStatus = res.isLoggedIn;
console.log("LOGGEDINSTATUS:", this.loggedInStatus);
}, (err) => {
this.handleError(err);
});
}
registerUser(user: User): Observable<any> {
console.log("Mapping your request to appropriate route from Front End Service.");
console.log("User: ", user);
const cpHeaders = new HttpHeaders({'Content-Type': 'application/json'});
const options = {headers: cpHeaders};
return this.http.post(this.baseUrl + '/register-user', user, options)
.pipe(shareReplay(1))
.pipe(catchError(err => this.handleError(err)));
}
authenticateUser(creds: Credentials): Observable<any> {
console.log("Mapping your request to appropriate route from Front End Service.");
console.log("Credentials: ", creds);
const cpHeaders = new HttpHeaders({'Content-Type': 'application/json'});
const options = {headers: cpHeaders, withCredentials: true};
return this.http.post(this.baseUrl + '/auth-user', creds, options)
.pipe(shareReplay(1))
.pipe(catchError(err => this.handleError(err)));
}
private handleError(error: any){
console.error(error.message || error);
return throwError(error.status);
}
}
AuthGuard
import { Injectable } from '@angular/core';
import { CanActivate, CanActivateChild, CanLoad, Route, UrlSegment, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
constructor(
private authService: AuthService,
private router: Router
){ }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
this.authService.getIsLoggedIn();
const loggedIn = this.authService.loggedIn;
console.log("GUARD", loggedIn);
if(loggedIn){
return true;
}else{
this.router.navigate(['']);
}
}
canActivateChild(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return true;
}
canLoad(
route: Route,
segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean {
return true;
}
}
auth.js(路线)
const express = require('express');
const router = express.Router();
const authService = require('../Services/Service');
const util = require('../Utilities/util');
router.post('/register-user', (req, res) => {
console.log(">>> Routing you requests to backend services");
authService.registerUser(req.body, (data) => {
sess = req.session;
sess.email = req.body.email;
console.log(">>> Setting up a cookie-session \n"+">>>", sess);
res.send(data);
});
});
router.get('/auth-admin', (req, res) => {
authService.authenticateAdmin(req.query, (data) => {
res.send(data);
});
});
router.post('/auth-user', (req, res) => {
console.log(">>> Routing you requests to backend services");
authService.authenticateUser(req.body, (data) => {
sess = req.session;
if(data.statusCode == util.statusCode.OK){
sess.email = req.body.email;
}
console.log(">>> Setting up a cookie-session \n"+">>>", sess);
res.send(data);
});
});
// Check if user is logged in.
router.get('/login', (req, res) => {
console.log(">>> Check if user is logged in \n >>>", req.session.email);
req.session.email ? res.status(200).send({isLoggedIn: true}) : res.status(200).send({isLoggedIn: false})
});
module.exports = router;
Server.js
const app = require('express')();
const server = require('http').Server(app);
const bodyParser = require('body-parser');
const express = require('express');
const cors = require('cors');
const http = require('http');
const path = require('path');
const session = require('express-session');
let routes = require('./Routes/auth');
let util = require('./Utilities/util');
app.use(session({secret: 'mlwacvbspaurfyp',saveUninitialized: true,resave: true, cookie: { maxAge: 1 * 60 * 60 * 1000 }}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// To avoid cors browser exception.
app.use(cors({origin: [
"http://localhost:4200"
], credentials: true}));
app.use(function(err, req, res, next) {
return res.send({ "statusCode": util.statusCode.ONE, "statusMessage": util.statusMessage.SOMETHING_WENT_WRONG });
});
// app.use(express.static(path.join(__dirname, 'public')));
app.use(routes);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next();
});
/*first API to check if server is running*/
// app.get('*', (req, res) => {
// res.sendFile(path.join(__dirname, '../server/client/dist/index.html'));
// });
server.listen(3000,function(){
console.log('app listening on port: 3000');
});
更改身份验证服务中的方法,如下所述:-
async loggedIn() {
await this.getIsLoggedIn().toPromise();
return this.loggedInStatus;
}
getIsLoggedIn() {
return this.http.get(this.baseUrl + '/login', {
withCredentials: true
}).pipe(map((res: any) => {
this.loggedInStatus = res.isLoggedIn;
return true;
}), catchError((err) => {
return this.handleError(err);
}));
}
当我第一次尝试登录时,它确实对用户进行了身份验证,并将 AuthService 中的 loggedInStatus 设置为 true,但 AuthGuard 中的 loggedIn 设置为 false,因此不允许导航到仪表板。还有 console.logs 是乱序的,即首先记录 GUARD,然后记录 LOGGEDINSTATUS,而它应该与此相反。在我第二次尝试成功登录并导航到仪表板后,在重新加载页面时,它会将我重定向到登录页面,并且 AuthGaurd 中 loggedIn 的值未定义。
登录组件 Typescript
import { Component, OnInit } from '@angular/core';
import { FormGroup, Validators, FormBuilder, NgForm } from '@angular/forms';
import { Router } from '@angular/router';
import { Credentials } from '../Services/models';
import { AuthService } from '../Services/auth/auth.service';
import * as util from '../../../Server/Utilities/util';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
hide = true;
constructor(
private authService: AuthService,
private formBuilder: FormBuilder,
private router: Router
) {
this.loginForm = this.formBuilder.group({
email: ['', [Validators.required, Validators.email]],
pass: ['', [Validators.required, Validators.minLength(6)]]
});
}
ngOnInit() {
}
auth(form: NgForm){
event.preventDefault();
event.stopPropagation();
let creds: Credentials = {
email: this.loginForm.controls.email.value,
password: this.loginForm.controls.pass.value
}
this.authService.authenticateUser(creds).subscribe((data: any) => {
if(data.statusCode == util.statusCode.OK) {
form.resetForm();
this.router.navigate(['dashboard']);
}
else{
console.log("resp", data);
}
});
}
}
授权服务
import { Response, Headers, URLSearchParams, RequestOptions } from '@angular/http';
import { Observable, throwError } from 'rxjs';
import { map, catchError, shareReplay } from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { User, Credentials } from '../models';
@Injectable({
providedIn: 'root'
})
export class AuthService {
baseUrl = 'http://localhost:3000';
private loggedInStatus: boolean;
constructor( private http: HttpClient ) {
this.getIsLoggedIn();
}
get loggedIn() : boolean {
this.getIsLoggedIn();
return this.loggedInStatus;
}
getIsLoggedIn() {
this.http.get(this.baseUrl + '/login', {
withCredentials: true
}).subscribe((res: any) => {
this.loggedInStatus = res.isLoggedIn;
console.log("LOGGEDINSTATUS:", this.loggedInStatus);
}, (err) => {
this.handleError(err);
});
}
registerUser(user: User): Observable<any> {
console.log("Mapping your request to appropriate route from Front End Service.");
console.log("User: ", user);
const cpHeaders = new HttpHeaders({'Content-Type': 'application/json'});
const options = {headers: cpHeaders};
return this.http.post(this.baseUrl + '/register-user', user, options)
.pipe(shareReplay(1))
.pipe(catchError(err => this.handleError(err)));
}
authenticateUser(creds: Credentials): Observable<any> {
console.log("Mapping your request to appropriate route from Front End Service.");
console.log("Credentials: ", creds);
const cpHeaders = new HttpHeaders({'Content-Type': 'application/json'});
const options = {headers: cpHeaders, withCredentials: true};
return this.http.post(this.baseUrl + '/auth-user', creds, options)
.pipe(shareReplay(1))
.pipe(catchError(err => this.handleError(err)));
}
private handleError(error: any){
console.error(error.message || error);
return throwError(error.status);
}
}
AuthGuard
import { Injectable } from '@angular/core';
import { CanActivate, CanActivateChild, CanLoad, Route, UrlSegment, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
constructor(
private authService: AuthService,
private router: Router
){ }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
this.authService.getIsLoggedIn();
const loggedIn = this.authService.loggedIn;
console.log("GUARD", loggedIn);
if(loggedIn){
return true;
}else{
this.router.navigate(['']);
}
}
canActivateChild(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return true;
}
canLoad(
route: Route,
segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean {
return true;
}
}
auth.js(路线)
const express = require('express');
const router = express.Router();
const authService = require('../Services/Service');
const util = require('../Utilities/util');
router.post('/register-user', (req, res) => {
console.log(">>> Routing you requests to backend services");
authService.registerUser(req.body, (data) => {
sess = req.session;
sess.email = req.body.email;
console.log(">>> Setting up a cookie-session \n"+">>>", sess);
res.send(data);
});
});
router.get('/auth-admin', (req, res) => {
authService.authenticateAdmin(req.query, (data) => {
res.send(data);
});
});
router.post('/auth-user', (req, res) => {
console.log(">>> Routing you requests to backend services");
authService.authenticateUser(req.body, (data) => {
sess = req.session;
if(data.statusCode == util.statusCode.OK){
sess.email = req.body.email;
}
console.log(">>> Setting up a cookie-session \n"+">>>", sess);
res.send(data);
});
});
// Check if user is logged in.
router.get('/login', (req, res) => {
console.log(">>> Check if user is logged in \n >>>", req.session.email);
req.session.email ? res.status(200).send({isLoggedIn: true}) : res.status(200).send({isLoggedIn: false})
});
module.exports = router;
Server.js
const app = require('express')();
const server = require('http').Server(app);
const bodyParser = require('body-parser');
const express = require('express');
const cors = require('cors');
const http = require('http');
const path = require('path');
const session = require('express-session');
let routes = require('./Routes/auth');
let util = require('./Utilities/util');
app.use(session({secret: 'mlwacvbspaurfyp',saveUninitialized: true,resave: true, cookie: { maxAge: 1 * 60 * 60 * 1000 }}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// To avoid cors browser exception.
app.use(cors({origin: [
"http://localhost:4200"
], credentials: true}));
app.use(function(err, req, res, next) {
return res.send({ "statusCode": util.statusCode.ONE, "statusMessage": util.statusMessage.SOMETHING_WENT_WRONG });
});
// app.use(express.static(path.join(__dirname, 'public')));
app.use(routes);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next();
});
/*first API to check if server is running*/
// app.get('*', (req, res) => {
// res.sendFile(path.join(__dirname, '../server/client/dist/index.html'));
// });
server.listen(3000,function(){
console.log('app listening on port: 3000');
});
更改身份验证服务中的方法,如下所述:-
async loggedIn() {
await this.getIsLoggedIn().toPromise();
return this.loggedInStatus;
}
getIsLoggedIn() {
return this.http.get(this.baseUrl + '/login', {
withCredentials: true
}).pipe(map((res: any) => {
this.loggedInStatus = res.isLoggedIn;
return true;
}), catchError((err) => {
return this.handleError(err);
}));
}