【发布时间】:2020-03-05 14:02:24
【问题描述】:
我是 Angular 的初学者,所以请多多包涵。
我有一个简单的应用程序,它允许人们注册、登录和检索他们自己的用户数据(这是我坚持的部分)。
后台user.routes.js:
const auth = require('./middlewares/auth')
module.exports = (app) => {
const user = require('./user.controller.js');
app.post('/login', user.login);
app.post('/register', user.register);
app.get('/getuser', auth, user.getuser);
}
后台user.controller.js:
exports.getuser = async (req, res, next) => {
let user
try {
user = await User.findById(req.payload._id)
} catch (err) {
next(new InternalServerError('Could not fetch user', err))
return
}
if (!user) {
next(new NotFoundError('User not found'))
return
}
res.json(
pick(user, [
'email',
'firstName',
'lastName',
'accountType'
])
)
}
后台user.service.ts:
@Injectable()
export class UserService {
private _isLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject(false);
public readonly isLoggedIn$ = this._isLoggedIn.asObservable();
constructor(private http: HttpClient) {
this._isLoggedIn.next(this.isLoggedIn());
}
login(
email: string,
password: string,
rememberMe = false
): Observable<boolean | any> {
return this.http
.post<LoginResponse>('http://localhost:3001/login', { email, password })
.map(res => {
setToken(res.token, rememberMe);
this._isLoggedIn.next(true);
return true;
})
.catch(this.handleError);
}
register(
email: string,
password: string,
lastName: string,
firstName: string
): Observable<boolean | any> {
return this.http
.post<LoginResponse>('http://localhost:3001/register', {
email,
password,
lastName,
firstName
})
.map(res => {
setToken(res.token);
return true;
})
.catch(this.handleError);
}
logout() {
removeToken();
}
isLoggedIn() {
return tokenNotExpired();
}
getProfile() {
return this.http.get<Profile>('http://localhost:3001/getuser');
}
最后,我的后端auth.js:
// Dependencies
import { JwtHelperService } from '@auth0/angular-jwt';
// Angular
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest
} from '@angular/common/http';
import { Injectable } from '@angular/core';
// RXJS
import { Observable } from 'rxjs/Observable';
// Environment
import { DecodedToken } from './decoded-token';
// Services
const helper = new JwtHelperService();
// Constants
export const TOKEN_NAME = 'access_token';
// Exports
export function getToken(storage = null) {
if (storage) {
const token = storage.getItem(TOKEN_NAME);
if (token && !helper.isTokenExpired(token)) {
return token;
}
removeToken(storage);
return null;
}
return getToken(localStorage) || getToken(sessionStorage);
}
export function setToken(token: string, rememberMe = false) {
const storage = rememberMe ? localStorage : sessionStorage;
storage.setItem(TOKEN_NAME, token);
}
export function removeToken(storage = null) {
if (storage) {
storage.removeItem(TOKEN_NAME);
} else {
localStorage.removeItem(TOKEN_NAME);
sessionStorage.removeItem(TOKEN_NAME);
}
}
export function tokenNotExpired() {
return !helper.isTokenExpired(getToken());
}
export function decodeToken(): DecodedToken {
return helper.decodeToken(getToken());
}
@Injectable()
export class JwtHttpInterceptor implements HttpInterceptor {
constructor() {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const token = getToken();
let clone: HttpRequest<any>;
if (token) {
clone = request.clone({
setHeaders: {
Accept: `application/json`,
'Content-Type': `application/json`,
Authorization: `Bearer ${token}`
}
});
} else {
clone = request.clone({
setHeaders: {
Accept: `application/json`,
'Content-Type': `application/json`
}
});
}
return next.handle(clone);
}
}
在我的仪表板上,我做了一个非常简单的请求:
this.userService.getProfile().subscribe(data => (this.profile = data));
现在,我的问题如下:
使用 Postman,如果我向 /login 发出 POST 请求,我会得到一个令牌。到目前为止一切都很好。如果我在对/getuser 的下一个GET 请求中使用这个令牌(在邮递员中),我也会得到我想要的结果(用户的电子邮件、名字、姓氏、帐户类型)。
但是,问题出在前端。我登录并到达主页(那里没有问题),但是一旦调用 getProfile() ,我就会得到一个 GET http://localhost:3001/getuser 401 (Unauthorized) 。我已经坚持了好几个小时了,不知道问题出在哪里。
感谢我能得到的任何帮助。
谢谢!
【问题讨论】:
-
您是否检查过(使用 DevTools)发送到 API 的请求是否包含
Authorization标头? -
这可能是问题所在。但是我想用我设置 auth.js 的方式,请求应该包含 Authorization 标头?我该如何解决这个@KamilChlebek?