
身份驗證是任何 Web 應(yīng)用程序中最重要的部分之一。本教程討論基于令牌的身份驗證系統(tǒng)以及它們與傳統(tǒng)登錄系統(tǒng)的區(qū)別。在本教程結(jié)束時,您將看到一個用 Angular 和 Node.js 編寫的完整工作演示。
傳統(tǒng)身份驗證系統(tǒng)
在繼續(xù)基于令牌的身份驗證系統(tǒng)之前,讓我們先看一下傳統(tǒng)的身份驗證系統(tǒng)。
- 用戶在登錄表單中提供用戶名和密碼,然后點擊登錄。
- 發(fā)出請求后,通過查詢數(shù)據(jù)庫在后端驗證用戶。如果請求有效,則使用從數(shù)據(jù)庫中獲取的用戶信息創(chuàng)建會話,然后在響應(yīng)頭中返回會話信息,以便將會話ID存儲在瀏覽器中。
- 提供用于訪問應(yīng)用程序中受限端點的會話信息。
- 如果會話信息有效,則讓用戶訪問指定端點,并使用呈現(xiàn)的 HTML 內(nèi)容進行響應(yīng)。

到目前為止一切都很好。 Web 應(yīng)用程序運行良好,并且能夠?qū)τ脩暨M行身份驗證,以便他們可以訪問受限端點。但是,當您想為您的應(yīng)用程序開發(fā)另一個客戶端(例如 Android 客戶端)時會發(fā)生什么情況?您是否能夠使用當前的應(yīng)用程序來驗證移動客戶端并提供受限制的內(nèi)容?就目前情況而言,沒有。造成這種情況的主要原因有兩個:
- 會話和 Cookie 對于移動應(yīng)用程序沒有意義。您無法與移動客戶端共享在服務(wù)器端創(chuàng)建的會話或 Cookie。
- 在當前應(yīng)用程序中,返回呈現(xiàn)的 HTML。在移動客戶端中,您需要包含 JSON 或 XML 等內(nèi)容作為響應(yīng)。
在這種情況下,您需要一個獨立于客戶端的應(yīng)用程序。
基于令牌的身份驗證
在基于令牌的身份驗證中,不會使用 cookie 和會話。令牌將用于對向服務(wù)器發(fā)出的每個請求進行用戶身份驗證。讓我們使用基于令牌的身份驗證重新設(shè)計第一個場景。
它將使用以下控制流程:
- 用戶在登錄表單中提供用戶名和密碼,然后點擊登錄。
- 發(fā)出請求后,通過在數(shù)據(jù)庫中查詢來驗證后端的用戶。如果請求有效,則使用從數(shù)據(jù)庫獲取的用戶信息創(chuàng)建令牌,然后在響應(yīng)標頭中返回該信息,以便我們可以將令牌瀏覽器存儲在本地存儲中。
- 在每個請求標頭中提供令牌信息,以訪問應(yīng)用程序中的受限端點。
- 如果從請求標頭信息中獲取的令牌有效,則讓用戶訪問指定端點,并使用 JSON 或 XML 進行響應(yīng)。
在這種情況下,我們沒有返回會話或cookie,也沒有返回任何HTML內(nèi)容。這意味著我們可以將此架構(gòu)用于任何客戶端的特定應(yīng)用程序。您可以看到下面的架構(gòu)架構(gòu):

那么這個 JWT 是什么?
JWT
JWT 代表 JSON Web 令牌,是授權(quán)標頭中使用的令牌格式。該令牌可幫助您以安全的方式設(shè)計兩個系統(tǒng)之間的通信。出于本教程的目的,我們將 JWT 重新表述為“不記名令牌”。不記名令牌由三部分組成:標頭、負載和簽名。
-
標頭是令牌中保存令牌類型和加密方法的部分,也是使用 Base-64 進行加密的。
-
有效負載包含信息。您可以輸入任何類型的數(shù)據(jù),例如用戶信息、產(chǎn)品信息等,所有這些數(shù)據(jù)都使用 Base-64 加密進行存儲。
-
簽名由標頭、負載和密鑰的組合組成。密鑰必須安全地保存在服務(wù)器端。
您可以在下面看到 JWT 架構(gòu)和示例令牌:

您不需要實現(xiàn)不記名令牌生成器,因為您可以找到多種語言的已建立包。您可以在下面看到其中一些:
Node.js |
https://github.com/auth0/node-jsonwebtoken |
PHP |
http://github.com/firebase/php-jwt |
Java |
http://github.com/auth0/java-jwt |
紅寶石 |
https://github.com/jwt/ruby-jwt |
.NET |
https://github.com/auth0/java-jwt |
Python |
http://github.com/progrium/pyjwt/ |
一個實際示例
介紹了有關(guān)基于令牌的身份驗證的一些基本信息后,我們現(xiàn)在可以繼續(xù)討論一個實際示例??匆幌孪旅娴募軜?gòu),然后我們將更詳細地分析它:

- 多個客戶端(例如網(wǎng)絡(luò)應(yīng)用程序或移動客戶端)出于特定目的向 API 發(fā)出請求。
- 請求是向
https://api.yourexampleapp.com
等服務(wù)發(fā)出的。如果很多人使用該應(yīng)用程序,則可能需要多個服務(wù)器來提供請求的操作。
- 這里,負載均衡器用于平衡請求,以最適合后端的應(yīng)用程序服務(wù)器。當您向
https://api.yourexampleapp.com
發(fā)出請求時,負載均衡器首先會處理請求,然后會將客戶端重定向到特定服務(wù)器。
- 有一個應(yīng)用程序,并且該應(yīng)用程序部署到多臺服務(wù)器(server-1、server-2、...、server-n)。每當向
https://api.yourexampleapp.com
發(fā)出請求時,后端應(yīng)用程序都會攔截請求標頭并從授權(quán)標頭中提取令牌信息。將使用此令牌進行數(shù)據(jù)庫查詢。如果此令牌有效并且具有訪問所請求端點所需的權(quán)限,則它將繼續(xù)。如果沒有,它將返回 403 響應(yīng)代碼(表示禁止狀態(tài))。
優(yōu)點
基于令牌的身份驗證具有解決嚴重問題的多個優(yōu)點。以下是其中的一些:
獨立于客戶端的服務(wù)
在基于令牌的身份驗證中,令牌通過請求標頭傳輸,而不是將身份驗證信息保留在會話或 cookie 中。這意味著沒有狀態(tài)。您可以從任何類型的可以發(fā)出 HTTP 請求的客戶端向服務(wù)器發(fā)送請求。
內(nèi)容分發(fā)網(wǎng)絡(luò) (CDN)
在當前的大多數(shù) Web 應(yīng)用程序中,視圖在后端呈現(xiàn),HTML 內(nèi)容返回到瀏覽器。前端邏輯依賴于后端代碼。
沒有必要建立這樣的依賴關(guān)系。這帶來了幾個問題。例如,如果您正在與實現(xiàn)前端 HTML、CSS 和 JavaScript 的設(shè)計機構(gòu)合作,您需要將該前端代碼遷移到后端代碼中,以便進行一些渲染或填充操作。一段時間后,您呈現(xiàn)的 HTML 內(nèi)容將與代碼機構(gòu)實現(xiàn)的內(nèi)容有很大不同。
在基于令牌的身份驗證中,您可以與后端代碼分開開發(fā)前端項目。您的后端代碼將返回 JSON 響應(yīng),而不是渲染的 HTML,并且您可以將前端代碼的縮小、gzip 版本放入 CDN 中。當您訪問網(wǎng)頁時,HTML 內(nèi)容將從 CDN 提供,并且頁面內(nèi)容將由 API 服務(wù)使用授權(quán)標頭中的令牌填充。
無 Cookie 會話(或無 CSRF)
CSRF 是現(xiàn)代網(wǎng)絡(luò)安全中的一個主要問題,因為它不檢查請求源是否可信。為了解決這個問題,使用令牌池在每個表單帖子上發(fā)送該令牌。在基于令牌的身份驗證中,令牌用于授權(quán)標頭,而 CSRF 不包含該信息。
持久令牌存儲??
當應(yīng)用程序中進行會話讀、寫或刪除操作時,它會在操作系統(tǒng)的 temp
文件夾中進行文件操作,至少第一次是這樣。假設(shè)您有多個服務(wù)器,并且在第一臺服務(wù)器上創(chuàng)建了一個會話。當您發(fā)出另一個請求并且您的請求落入另一臺服務(wù)器時,會話信息將不存在并且將得到“未經(jīng)授權(quán)”的響應(yīng)。我知道,你可以通過粘性會話來解決這個問題。然而,在基于令牌的認證中,這種情況自然就解決了。不存在粘性會話問題,因為請求令牌在任何服務(wù)器上的每個請求上都會被攔截。
這些是基于令牌的身份驗證和通信的最常見優(yōu)點。關(guān)于基于令牌的身份驗證的理論和架構(gòu)討論就到此結(jié)束。是時候看一個實際例子了。
示例應(yīng)用程序
您將看到兩個應(yīng)用程序來演示基于令牌的身份驗證:
- 基于令牌的身份驗證后端
- 基于令牌的身份驗證前端
在后端項目中,會有服務(wù)的實現(xiàn),服務(wù)結(jié)果將是JSON格式。服務(wù)中沒有返回視圖。在前端項目中,將有一個用于前端 HTML 的 Angular 項目,然后前端應(yīng)用程序?qū)⒂?Angular 服務(wù)填充,以向后端服務(wù)發(fā)出請求。
基于令牌的身份驗證后端
在后端項目中,主要有三個文件:
-
package.json 用于依賴管理。
-
models/User.js 包含一個用戶模型,用于對用戶進行數(shù)據(jù)庫操作。
-
server.js 用于項目引導(dǎo)和請求處理。
就是這樣!這個項目非常簡單,因此您無需深入研究即可輕松理解主要概念。
{
"name": "angular-restful-auth",
"version": "0.0.1",
"dependencies": {
"body-parser": "^1.20.2",
"express": "4.x",
"express-jwt": "8.4.1",
"jsonwebtoken": "9.0.0",
"mongoose": "7.3.1",
"morgan": "latest"
},
"engines": {
"node": ">=0.10.0"
}
}
?
package.json 包含項目的依賴項: express
用于 MVC,body-parser
express
用于 MVC,body-parser
用于模擬 post Node.js 中的請求處理,morgan
用于請求日志記錄,mongoose
用于我們的 ORM 框架連接到 MongoDB,和 jsonwebtoken
用于使用我們的用戶模型創(chuàng)建 JWT 令牌。還有一個名為 engines
用于模擬 post Node.js 中的請求處理,
morgan
用于請求日志記錄,mongoose
用于我們的 ORM 框架連接到 MongoDB,和
jsonwebtoken
用于使用我們的用戶模型創(chuàng)建 JWT 令牌。還有一個名為
engines
的屬性,表示該項目是使用 Node.js 版本 >= 0.10.0 制作的。這對于 Heroku 等 PaaS 服務(wù)很有用。我們還將在另一節(jié)中討論該主題。
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
email: String,
password: String,
token: String
});
module.exports = mongoose.model('User', UserSchema);
?
我們說過我們將使用用戶模型有效負載生成令牌。這個模型幫助我們對MongoDB進行用戶操作。在
User.jsrequire
中,定義了用戶模式并使用貓鼬模型創(chuàng)建了用戶模型。該模型已準備好進行數(shù)據(jù)庫操作。
我們的依賴關(guān)系已經(jīng)定義,我們的用戶模型也已經(jīng)定義,所以現(xiàn)在讓我們將所有這些組合起來構(gòu)建一個用于處理特定請求的服務(wù)。3001
。之后,包含了User模型,并建立了數(shù)據(jù)庫連接,以進行一些用戶操作。不要忘記為數(shù)據(jù)庫連接 URL 定義一個環(huán)境變量 MONGO_URL
// Required Modules
const express = require("express");
const morgan = require("morgan");
const bodyParser = require("body-parser");
const jwt = require("jsonwebtoken");
const mongoose = require("mongoose");
const app = express();
?
在 Node.js 中,您可以使用
在項目中包含模塊。首先,我們需要將必要的模塊導(dǎo)入到項目中:
const port = process.env.PORT || 3001;
const User = require('./models/User');
// Connect to DB
mongoose.connect(process.env.MONGO_URL);
?
??我們的服務(wù)將通過特定端口提供服務(wù)。如果系統(tǒng)環(huán)境變量中定義了任何端口變量,則可以使用它,或者我們定義了端口 ??。??
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan("dev"));
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
next();
});
?
??在上面的部分中,我們使用 Express 進行了一些配置來模擬 Node 中的 HTTP 請求處理。我們允許來自不同域的請求,以便開發(fā)獨立于客戶端的系統(tǒng)。如果您不允許這樣做,您將在網(wǎng)絡(luò)瀏覽器中觸發(fā) CORS(跨源請求共享)錯誤。??
-
Access-Control-Allow-Origin
允許所有域。
- 您可以向此服務(wù)發(fā)送
POST
和 GET
請求。
-
X-Requested-With
和 content-type
標頭是允許的。
app.post('/authenticate', async function(req, res) {
try {
const user = await User.findOne({ email: req.body.email, password: req.body.password }).exec();
if (user) {
res.json({
type: true,
data: user,
token: user.token
});
} else {
res.json({
type: false,
data: "Incorrect email/password"
});
}
} catch (err) {
res.json({
type: false,
data: "Error occurred: " + err
});
}
});
?
我們已經(jīng)導(dǎo)入了所有必需的模塊并定義了我們的配置,所以現(xiàn)在是時候定義請求處理程序了。在上面的代碼中,每當你使用用戶名和密碼向 /authenticate
發(fā)出 POST
請求時,你都會得到一個 JWT
令牌。首先,使用用戶名和密碼處理數(shù)據(jù)庫查詢。如果用戶存在,則用戶數(shù)據(jù)將與其令牌一起返回。但是如果沒有與用戶名和/或密碼匹配的用戶怎么辦?
app.post('/signin', async function(req, res) {
try {
const existingUser = await User.findOne({ email: req.body.email }).exec();
if (existingUser) {
res.json({
type: false,
data: "User already exists!"
});
} else {
const userModel = new User();
userModel.email = req.body.email;
userModel.password = req.body.password;
const savedUser = await userModel.save();
savedUser.token = jwt.sign(savedUser.toObject(), process.env.JWT_SECRET);
const updatedUser = await savedUser.save();
res.json({
type: true,
data: updatedUser,
token: updatedUser.token
});
}
} catch (err) {
res.json({
type: false,
data: "Error occurred: " + err
});
}
});
?
當您使用用戶名和密碼向 /signin
發(fā)出 POST
請求時,將使用發(fā)布的用戶信息創(chuàng)建一個新用戶。在 14th
行,您可以看到使用 jsonwebtoken
模塊生成了一個新的 JSON 令牌,該令牌已分配給 jwt
變量。認證部分沒問題。如果我們嘗試訪問受限端點怎么辦?我們?nèi)绾卧O(shè)法訪問該端點?
app.get('/me', ensureAuthorized, async function(req, res) {
try {
const user = await User.findOne({ token: req.token }).exec();
res.json({
type: true,
data: user
});
} catch (err) {
res.json({
type: false,
data: "Error occurred: " + err
});
}
});
?
當您向 /me
發(fā)出 GET
請求時,您將獲得當前用戶信息,但為了繼續(xù)請求的端點,確保Authorized
函數(shù)將被執(zhí)行。
function ensureAuthorized(req, res, next) {
var bearerToken;
var bearerHeader = req.headers["authorization"];
if (typeof bearerHeader !== 'undefined') {
var bearer = bearerHeader.split(" ");
bearerToken = bearer[1];
req.token = bearerToken;
next();
} else {
res.send(403);
}
}
?
在該函數(shù)中,攔截請求頭,并提取authorization
頭。如果此標頭中存在承載令牌,則該令牌將分配給 req.token
以便在整個請求中使用,并且可以使用 next( )
。如果令牌不存在,您將收到 403(禁止)響應(yīng)。讓我們回到處理程序 /me
,并使用 req.token
使用此令牌獲取用戶數(shù)據(jù)。每當您創(chuàng)建新用戶時,都會生成一個令牌并將其保存在數(shù)據(jù)庫的用戶模型中。這些令牌是獨一無二的。
對于這個簡單的項目,我們只有三個處理程序。之后,您將看到:
process.on('uncaughtException', function(err) {
console.log(err);
});
?
如果發(fā)生錯誤,Node.js 應(yīng)用程序可能會崩潰。使用上面的代碼,可以防止崩潰,并在控制臺中打印錯誤日志。最后,我們可以使用以下代碼片段啟動服務(wù)器。
// Start Server
app.listen(port, function () {
console.log( "Express server listening on port " + port);
});
?
總結(jié)一下:
- 模塊已導(dǎo)入。
- 配置已完成。
- 已定義請求處理程序。
- 定義中間件是為了攔截受限端點。
- 服務(wù)器已啟動。
我們已經(jīng)完成了后端服務(wù)。為了讓多個客戶端可以使用它,您可以將這個簡單的服務(wù)器應(yīng)用程序部署到您的服務(wù)器上,或者也可以部署在 Heroku 中。項目根文件夾中有一個名為 Procfile
的文件。讓我們在 Heroku 中部署我們的服務(wù)。
Heroku 部署
您可以從此 GitHub 存儲庫克隆后端項目。
我不會討論如何在 Heroku 中創(chuàng)建應(yīng)用程序;如果您之前沒有創(chuàng)建過 Heroku 應(yīng)用程序,可以參考這篇文章來創(chuàng)建 Heroku 應(yīng)用程序。創(chuàng)建 Heroku 應(yīng)用程序后,您可以使用以下命令將目標添加到當前項目:
git remote add heroku <your_heroku_git_url>
現(xiàn)在您已經(jīng)克隆了一個項目并添加了一個目標。在 git add
和 git commit
之后,您可以通過執(zhí)行 git push heroku master
將代碼推送到 Heroku。當您成功推送項目時,Heroku 將執(zhí)行 npm install
命令將依賴項下載到 Heroku 上的 temp
文件夾中。之后,它將啟動您的應(yīng)用程序,您可以使用 HTTP 協(xié)議訪問您的服務(wù)。
基于令牌的-auth-frontend
在前端項目中,您將看到一個 Angular 項目。在這里,我只提及前端項目中的主要部分,因為 Angular 不是一個教程可以涵蓋的內(nèi)容。
您可以從此 GitHub 存儲庫克隆該項目。在此項目中,您將看到以下文件夾結(jié)構(gòu):

我們擁有三個組件——注冊、配置文件和登錄——以及一個身份驗證服務(wù)。
您的app.component.html 如下所示:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap demo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid">
<a class="navbar-brand" href="#">Home</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item"><a class="nav-link" routerLink="/profile">Me</a></li>
<li class="nav-item"><a class="nav-link" routerLink="/login">Signin</a></li>
<li class="nav-item"><a class="nav-link" routerLink="/signup">Signup</a></li>
<li class="nav-item"><a class="nav-link" (click)="logout()">Logout</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<router-outlet></router-outlet>
</div>
</body>
</html>
?
在主組件文件中,<router-outlet></router-outlet>
?定義各個組件的路由。
在 auth.service.ts 文件中,我們定義 AuthService
類,該類通過 API 調(diào)用來處理身份驗證,以登錄、驗證 Node.js 應(yīng)用程序的 API 端點。
import { Injectable } from '@angular/core';
import { HttpClient,HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private apiUrl = 'your_node_app_url';
public token: string ='';
constructor(private http: HttpClient) {
}
signin(username: string, password: string): Observable<any> {
const data = { username, password };
return this.http.post(`${this.apiUrl}/signin`, data);
}
authenticate(email: string, password: string): Observable<any> {
const data = { email, password };
console.log(data)
return this.http.post(`${this.apiUrl}/authenticate`, data)
.pipe(
tap((response:any) => {
this.token = response.data.token; // Store the received token
localStorage.setItem('token',this.token)
console.log(this.token)
})
);
}
profile(): Observable<any> {
const headers = this.createHeaders();
return this.http.get(`${this.apiUrl}/me`,{ headers });
}
private createHeaders(): HttpHeaders {
let headers = new HttpHeaders({
'Content-Type': 'application/json',
});
if (this.token) {
headers = headers.append('Authorization', `Bearer ${this.token}`);
}
return headers;
}
logout(): void {
localStorage.removeItem('token');
}
}
在 authenticate()
方法中,我們向 API 發(fā)送 POST 請求并對用戶進行身份驗證。從響應(yīng)中,我們提取令牌并將其存儲在服務(wù)的 this.token
屬性和瀏覽器的 localStorage
中,然后將響應(yīng)作為 Observable
返回。
在 profile()
方法中,我們通過在 Authorization 標頭中包含令牌來發(fā)出 GET 請求以獲取用戶詳細信息。
createHeaders()
方法在發(fā)出經(jīng)過身份驗證的 API 請求時創(chuàng)建包含身份驗證令牌的 HTTP 標頭。當用戶擁有有效令牌時,它會添加一個授權(quán)標頭。該令牌允許后端 API 對用戶進行身份驗證。
如果身份驗證成功,用戶令牌將存儲在本地存儲中以供后續(xù)請求使用。該令牌也可供所有組件使用。如果身份驗證失敗,我們會顯示一條錯誤消息。
不要忘記將服務(wù) URL 放入上面代碼中的 baseUrl
中。當您將服務(wù)部署到 Heroku 時,您將獲得類似 appname.herokuapp.com
的服務(wù) URL。在上面的代碼中,您將設(shè)置 var baseUrl = "appname.herokuapp.com"
。
注銷功能從本地存儲中刪除令牌。
在 signup.component.ts
文件中,我們實現(xiàn)了 signup ()
方法,該方法獲取用戶提交的電子郵件和密碼并創(chuàng)建一個新用戶。
import { Component } from '@angular/core';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-signup',
templateUrl: './signup.component.html',
styleUrls: ['./signup.component.css']
})
export class SignupComponent {
password: string = '';
email: string = '';
constructor(private authService:AuthService){}
signup(): void {
this.authService.signin(this.email, this.password).subscribe(
(response) => {
// success response
console.log('Authentication successful', response);
},
(error) => {
// error response
console.error('Authentication error', error);
}
);
}
}
?
login.component.ts 文件看起來與注冊組件類似。
?
import { Component } from '@angular/core';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent {
email: string = '';
password: string = '';
constructor(private authService: AuthService) {}
login(): void {
this.authService.authenticate(this.email, this.password).subscribe(
(response) => {
// success response
console.log('Signin successful', response);
},
(error) => {
// error response
console.error('Signin error', error);
}
);
}
}
配置文件組件使用用戶令牌來獲取用戶的詳細信息。每當您向后端的服務(wù)發(fā)出請求時,都需要將此令牌放入標頭中。 profile.component.ts 如下所示:
import { Component } from '@angular/core';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent {
myDetails: any;
constructor(private authService: AuthService) { }
ngOnInit(): void {
this.getProfileData();
}
getProfileData(): void {
this.authService.me().subscribe(
(response: any) => {
this.myDetails = response;
console.log('User Data:', this.myDetails);
},
(error: any) => {
console.error('Error retrieving profile data');
}
);
}
?
在上面的代碼中,每個請求都會被攔截,并在標頭中放入授權(quán)標頭和值。然后,我們將用戶詳細信息傳遞到 profile.component.html 模板。
<h2>User profile </h2>
<div class="row">
<div class="col-lg-12">
<p>{{myDetails.data.id}}</p>
<p>{{myDetails.data.email}}</p>
</div>
</div>
最后,我們在 app.routing.module.ts 中定義路由。
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { ProfileComponent } from './profile/profile.component';
import { SignupComponent } from './signup/signup.component';
const routes: Routes = [
{path:'signup' , component:SignupComponent},
{path:'login' , component:LoginComponent},
{ path: 'profile', component: ProfileComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
?
從上面的代碼中您可以很容易地理解,當您轉(zhuǎn)到/時,將呈現(xiàn)app.component.html頁面。另一個例子:如果您轉(zhuǎn)到/signup,則會呈現(xiàn)signup.component.html。這個渲染操作將在瀏覽器中完成,而不是在服務(wù)器端。
結(jié)論
基于令牌的身份驗證系統(tǒng)可幫助您在開發(fā)獨立于客戶端的服務(wù)時構(gòu)建身份驗證/授權(quán)系統(tǒng)。通過使用這項技術(shù),您將只需專注于您的服務(wù)(或 API)。
身份驗證/授權(quán)部分將由基于令牌的身份驗證系統(tǒng)作為服務(wù)前面的一層進行處理。您可以從任何客戶端(例如網(wǎng)絡(luò)瀏覽器、Android、iOS 或桌面客戶端)訪問和使用服務(wù)。
以上是使用Angular和Node進行基于令牌的身份驗證的詳細內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!