国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
傳統(tǒng)身份驗(yàn)證系統(tǒng)
基于令牌的身份驗(yàn)證
JWT
一個(gè)實(shí)際示例
優(yōu)點(diǎn)
獨(dú)立于客戶(hù)端的服務(wù)
內(nèi)容分發(fā)網(wǎng)絡(luò) (CDN)
無(wú) Cookie 會(huì)話(huà)(或無(wú) CSRF)
持久令牌存儲(chǔ)??
示例應(yīng)用程序
基于令牌的身份驗(yàn)證后端
Heroku 部署
基于令牌的-auth-frontend
結(jié)論
首頁(yè) CMS教程 &#&按 使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證

使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證

Sep 01, 2023 pm 02:01 PM
angular node 身份驗(yàn)證

使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證

身份驗(yàn)證是任何 Web 應(yīng)用程序中最重要的部分之一。本教程討論基于令牌的身份驗(yàn)證系統(tǒng)以及它們與傳統(tǒng)登錄系統(tǒng)的區(qū)別。在本教程結(jié)束時(shí),您將看到一個(gè)用 Angular 和 Node.js 編寫(xiě)的完整工作演示。

傳統(tǒng)身份驗(yàn)證系統(tǒng)

在繼續(xù)基于令牌的身份驗(yàn)證系統(tǒng)之前,讓我們先看一下傳統(tǒng)的身份驗(yàn)證系統(tǒng)。

  1. 用戶(hù)在登錄表單中提供用戶(hù)名密碼,然后點(diǎn)擊登錄。
  2. 發(fā)出請(qǐng)求后,通過(guò)查詢(xún)數(shù)據(jù)庫(kù)在后端驗(yàn)證用戶(hù)。如果請(qǐng)求有效,則使用從數(shù)據(jù)庫(kù)中獲取的用戶(hù)信息創(chuàng)建會(huì)話(huà),然后在響應(yīng)頭中返回會(huì)話(huà)信息,以便將會(huì)話(huà)ID存儲(chǔ)在瀏覽器中。
  3. 提供用于訪(fǎng)問(wèn)應(yīng)用程序中受限端點(diǎn)的會(huì)話(huà)信息。
  4. 如果會(huì)話(huà)信息有效,則讓用戶(hù)訪(fǎng)問(wèn)指定端點(diǎn),并使用呈現(xiàn)的 HTML 內(nèi)容進(jìn)行響應(yīng)。

使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證

到目前為止一切都很好。 Web 應(yīng)用程序運(yùn)行良好,并且能夠?qū)τ脩?hù)進(jìn)行身份驗(yàn)證,以便他們可以訪(fǎng)問(wèn)受限端點(diǎn)。但是,當(dāng)您想為您的應(yīng)用程序開(kāi)發(fā)另一個(gè)客戶(hù)端(例如 Android 客戶(hù)端)時(shí)會(huì)發(fā)生什么情況?您是否能夠使用當(dāng)前的應(yīng)用程序來(lái)驗(yàn)證移動(dòng)客戶(hù)端并提供受限制的內(nèi)容?就目前情況而言,沒(méi)有。造成這種情況的主要原因有兩個(gè):

  1. 會(huì)話(huà)和 Cookie 對(duì)于移動(dòng)應(yīng)用程序沒(méi)有意義。您無(wú)法與移動(dòng)客戶(hù)端共享在服務(wù)器端創(chuàng)建的會(huì)話(huà)或 Cookie。
  2. 在當(dāng)前應(yīng)用程序中,返回呈現(xiàn)的 HTML。在移動(dòng)客戶(hù)端中,您需要包含 JSON 或 XML 等內(nèi)容作為響應(yīng)。

在這種情況下,您需要一個(gè)獨(dú)立于客戶(hù)端的應(yīng)用程序。

基于令牌的身份驗(yàn)證

在基于令牌的身份驗(yàn)證中,不會(huì)使用 cookie 和會(huì)話(huà)。令牌將用于對(duì)向服務(wù)器發(fā)出的每個(gè)請(qǐng)求進(jìn)行用戶(hù)身份驗(yàn)證。讓我們使用基于令牌的身份驗(yàn)證重新設(shè)計(jì)第一個(gè)場(chǎng)景。

它將使用以下控制流程:

  1. 用戶(hù)在登錄表單中提供用戶(hù)名密碼,然后點(diǎn)擊登錄
  2. 發(fā)出請(qǐng)求后,通過(guò)在數(shù)據(jù)庫(kù)中查詢(xún)來(lái)驗(yàn)證后端的用戶(hù)。如果請(qǐng)求有效,則使用從數(shù)據(jù)庫(kù)獲取的用戶(hù)信息創(chuàng)建令牌,然后在響應(yīng)標(biāo)頭中返回該信息,以便我們可以將令牌瀏覽器存儲(chǔ)在本地存儲(chǔ)中。
  3. 在每個(gè)請(qǐng)求標(biāo)頭中提供令牌信息,以訪(fǎng)問(wèn)應(yīng)用程序中的受限端點(diǎn)。
  4. 如果從請(qǐng)求標(biāo)頭信息中獲取的令牌有效,則讓用戶(hù)訪(fǎng)問(wèn)指定端點(diǎn),并使用 JSON 或 XML 進(jìn)行響應(yīng)。

在這種情況下,我們沒(méi)有返回會(huì)話(huà)或cookie,也沒(méi)有返回任何HTML內(nèi)容。這意味著我們可以將此架構(gòu)用于任何客戶(hù)端的特定應(yīng)用程序。您可以看到下面的架構(gòu)架構(gòu):

使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證

那么這個(gè) JWT 是什么?

JWT

JWT 代表 JSON Web 令牌,是授權(quán)標(biāo)頭中使用的令牌格式。該令牌可幫助您以安全的方式設(shè)計(jì)兩個(gè)系統(tǒng)之間的通信。出于本教程的目的,我們將 JWT 重新表述為“不記名令牌”。不記名令牌由三部分組成:標(biāo)頭、負(fù)載和簽名。

  • 標(biāo)頭是令牌中保存令牌類(lèi)型和加密方法的部分,也是使用 Base-64 進(jìn)行加密的。
  • 有效負(fù)載包含信息。您可以輸入任何類(lèi)型的數(shù)據(jù),例如用戶(hù)信息、產(chǎn)品信息等,所有這些數(shù)據(jù)都使用 Base-64 加密進(jìn)行存儲(chǔ)。
  • 簽名由標(biāo)頭、負(fù)載和密鑰的組合組成。密鑰必須安全地保存在服務(wù)器端。

您可以在下面看到 JWT 架構(gòu)和示例令牌:

使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證

您不需要實(shí)現(xiàn)不記名令牌生成器,因?yàn)槟梢哉业蕉喾N語(yǔ)言的已建立包。您可以在下面看到其中一些:

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/

一個(gè)實(shí)際示例

介紹了有關(guān)基于令牌的身份驗(yàn)證的一些基本信息后,我們現(xiàn)在可以繼續(xù)討論一個(gè)實(shí)際示例。看一下下面的架構(gòu),然后我們將更詳細(xì)地分析它:

使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證

  1. 多個(gè)客戶(hù)端(例如網(wǎng)絡(luò)應(yīng)用程序或移動(dòng)客戶(hù)端)出于特定目的向 API 發(fā)出請(qǐng)求。
  2. 請(qǐng)求是向 https://api.yourexampleapp.com 等服務(wù)發(fā)出的。如果很多人使用該應(yīng)用程序,則可能需要多個(gè)服務(wù)器來(lái)提供請(qǐng)求的操作。
  3. 這里,負(fù)載均衡器用于平衡請(qǐng)求,以最適合后端的應(yīng)用程序服務(wù)器。當(dāng)您向 https://api.yourexampleapp.com 發(fā)出請(qǐng)求時(shí),負(fù)載均衡器首先會(huì)處理請(qǐng)求,然后會(huì)將客戶(hù)端重定向到特定服務(wù)器。
  4. 有一個(gè)應(yīng)用程序,并且該應(yīng)用程序部署到多臺(tái)服務(wù)器(server-1、server-2、...、server-n)。每當(dāng)向 https://api.yourexampleapp.com 發(fā)出請(qǐng)求時(shí),后端應(yīng)用程序都會(huì)攔截請(qǐng)求標(biāo)頭并從授權(quán)標(biāo)頭中提取令牌信息。將使用此令牌進(jìn)行數(shù)據(jù)庫(kù)查詢(xún)。如果此令牌有效并且具有訪(fǎng)問(wèn)所請(qǐng)求端點(diǎn)所需的權(quán)限,則它將繼續(xù)。如果沒(méi)有,它將返回 403 響應(yīng)代碼(表示禁止?fàn)顟B(tài))。

優(yōu)點(diǎn)

基于令牌的身份驗(yàn)證具有解決嚴(yán)重問(wèn)題的多個(gè)優(yōu)點(diǎn)。以下是其中的一些:

獨(dú)立于客戶(hù)端的服務(wù)

在基于令牌的身份驗(yàn)證中,令牌通過(guò)請(qǐng)求標(biāo)頭傳輸,而不是將身份驗(yàn)證信息保留在會(huì)話(huà)或 cookie 中。這意味著沒(méi)有狀態(tài)。您可以從任何類(lèi)型的可以發(fā)出 HTTP 請(qǐng)求的客戶(hù)端向服務(wù)器發(fā)送請(qǐng)求。

內(nèi)容分發(fā)網(wǎng)絡(luò) (CDN)

在當(dāng)前的大多數(shù) Web 應(yīng)用程序中,視圖在后端呈現(xiàn),HTML 內(nèi)容返回到瀏覽器。前端邏輯依賴(lài)于后端代碼。

沒(méi)有必要建立這樣的依賴(lài)關(guān)系。這帶來(lái)了幾個(gè)問(wèn)題。例如,如果您正在與實(shí)現(xiàn)前端 HTML、CSS 和 JavaScript 的設(shè)計(jì)機(jī)構(gòu)合作,您需要將該前端代碼遷移到后端代碼中,以便進(jìn)行一些渲染或填充操作。一段時(shí)間后,您呈現(xiàn)的 HTML 內(nèi)容將與代碼機(jī)構(gòu)實(shí)現(xiàn)的內(nèi)容有很大不同。

在基于令牌的身份驗(yàn)證中,您可以與后端代碼分開(kāi)開(kāi)發(fā)前端項(xiàng)目。您的后端代碼將返回 JSON 響應(yīng),而不是渲染的 HTML,并且您可以將前端代碼的縮小、gzip 版本放入 CDN 中。當(dāng)您訪(fǎng)問(wèn)網(wǎng)頁(yè)時(shí),HTML 內(nèi)容將從 CDN 提供,并且頁(yè)面內(nèi)容將由 API 服務(wù)使用授權(quán)標(biāo)頭中的令牌填充。

CSRF 是現(xiàn)代網(wǎng)絡(luò)安全中的一個(gè)主要問(wèn)題,因?yàn)樗粰z查請(qǐng)求源是否可信。為了解決這個(gè)問(wèn)題,使用令牌池在每個(gè)表單帖子上發(fā)送該令牌。在基于令牌的身份驗(yàn)證中,令牌用于授權(quán)標(biāo)頭,而 CSRF 不包含該信息。

持久令牌存儲(chǔ)??

當(dāng)應(yīng)用程序中進(jìn)行會(huì)話(huà)讀、寫(xiě)或刪除操作時(shí),它會(huì)在操作系統(tǒng)的 temp 文件夾中進(jìn)行文件操作,至少第一次是這樣。假設(shè)您有多個(gè)服務(wù)器,并且在第一臺(tái)服務(wù)器上創(chuàng)建了一個(gè)會(huì)話(huà)。當(dāng)您發(fā)出另一個(gè)請(qǐng)求并且您的請(qǐng)求落入另一臺(tái)服務(wù)器時(shí),會(huì)話(huà)信息將不存在并且將得到“未經(jīng)授權(quán)”的響應(yīng)。我知道,你可以通過(guò)粘性會(huì)話(huà)來(lái)解決這個(gè)問(wèn)題。然而,在基于令牌的認(rèn)證中,這種情況自然就解決了。不存在粘性會(huì)話(huà)問(wèn)題,因?yàn)檎?qǐng)求令牌在任何服務(wù)器上的每個(gè)請(qǐng)求上都會(huì)被攔截。

這些是基于令牌的身份驗(yàn)證和通信的最常見(jiàn)優(yōu)點(diǎn)。關(guān)于基于令牌的身份驗(yàn)證的理論和架構(gòu)討論就到此結(jié)束。是時(shí)候看一個(gè)實(shí)際例子了。

示例應(yīng)用程序

您將看到兩個(gè)應(yīng)用程序來(lái)演示基于令牌的身份驗(yàn)證:

  1. 基于令牌的身份驗(yàn)證后端
  2. 基于令牌的身份驗(yàn)證前端

在后端項(xiàng)目中,會(huì)有服務(wù)的實(shí)現(xiàn),服務(wù)結(jié)果將是JSON格式。服務(wù)中沒(méi)有返回視圖。在前端項(xiàng)目中,將有一個(gè)用于前端 HTML 的 Angular 項(xiàng)目,然后前端應(yīng)用程序?qū)⒂?Angular 服務(wù)填充,以向后端服務(wù)發(fā)出請(qǐng)求。

基于令牌的身份驗(yàn)證后端

在后端項(xiàng)目中,主要有三個(gè)文件:

  • package.json 用于依賴(lài)管理。
  • models/User.js 包含一個(gè)用戶(hù)模型,用于對(duì)用戶(hù)進(jìn)行數(shù)據(jù)庫(kù)操作。
  • server.js 用于項(xiàng)目引導(dǎo)和請(qǐng)求處理。

就是這樣!這個(gè)項(xiàng)目非常簡(jiǎn)單,因此您無(wú)需深入研究即可輕松理解主要概念。

{
    "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 包含項(xiàng)目的依賴(lài)項(xiàng): express 用于 MVC,body-parserexpress 用于 MVC,body-parser 用于模擬 post Node.js 中的請(qǐng)求處理,morgan 用于請(qǐng)求日志記錄,mongoose 用于我們的 ORM 框架連接到 MongoDB,和 jsonwebtoken 用于使用我們的用戶(hù)模型創(chuàng)建 JWT 令牌。還有一個(gè)名為 engines

用于模擬 post Node.js 中的請(qǐng)求處理,morgan

用于請(qǐng)求日志記錄,mongoose

用于我們的 ORM 框架連接到 MongoDB,和 jsonwebtoken 用于使用我們的用戶(hù)模型創(chuàng)建 JWT 令牌。還有一個(gè)名為 engines 的屬性,表示該項(xiàng)目是使用 Node.js 版本 >= 0.10.0 制作的。這對(duì)于 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);
?

我們說(shuō)過(guò)我們將使用用戶(hù)模型有效負(fù)載生成令牌。這個(gè)模型幫助我們對(duì)MongoDB進(jìn)行用戶(hù)操作。在

User.jsrequire中,定義了用戶(hù)模式并使用貓鼬模型創(chuàng)建了用戶(hù)模型。該模型已準(zhǔn)備好進(jìn)行數(shù)據(jù)庫(kù)操作。

我們的依賴(lài)關(guān)系已經(jīng)定義,我們的用戶(hù)模型也已經(jīng)定義,所以現(xiàn)在讓我們將所有這些組合起來(lái)構(gòu)建一個(gè)用于處理特定請(qǐng)求的服務(wù)。3001。之后,包含了User模型,并建立了數(shù)據(jù)庫(kù)連接,以進(jìn)行一些用戶(hù)操作。不要忘記為數(shù)據(jù)庫(kù)連接 URL 定義一個(gè)環(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 中,您可以使用

在項(xiàng)目中包含模塊。首先,我們需要將必要的模塊導(dǎo)入到項(xiàng)目中:

const port = process.env.PORT || 3001;
const User     = require('./models/User');

// Connect to DB
mongoose.connect(process.env.MONGO_URL);
? ??我們的服務(wù)將通過(guò)特定端口提供服務(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 進(jìn)行了一些配置來(lái)模擬 Node 中的 HTTP 請(qǐng)求處理。我們?cè)试S來(lái)自不同域的請(qǐng)求,以便開(kāi)發(fā)獨(dú)立于客戶(hù)端的系統(tǒng)。如果您不允許這樣做,您將在網(wǎng)絡(luò)瀏覽器中觸發(fā) CORS(跨源請(qǐng)求共享)錯(cuò)誤。??
  • Access-Control-Allow-Origin 允許所有域。
  • 您可以向此服務(wù)發(fā)送 POSTGET 請(qǐng)求。
  • X-Requested-Withcontent-type 標(biāo)頭是允許的。
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)在是時(shí)候定義請(qǐng)求處理程序了。在上面的代碼中,每當(dāng)你使用用戶(hù)名和密碼向 /authenticate 發(fā)出 POST 請(qǐng)求時(shí),你都會(huì)得到一個(gè) JWT 令牌。首先,使用用戶(hù)名和密碼處理數(shù)據(jù)庫(kù)查詢(xún)。如果用戶(hù)存在,則用戶(hù)數(shù)據(jù)將與其令牌一起返回。但是如果沒(méi)有與用戶(hù)名和/或密碼匹配的用戶(hù)怎么辦?

 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
      });
    }
  });
?

當(dāng)您使用用戶(hù)名和密碼向 /signin 發(fā)出 POST 請(qǐng)求時(shí),將使用發(fā)布的用戶(hù)信息創(chuàng)建一個(gè)新用戶(hù)。在 14th 行,您可以看到使用 jsonwebtoken 模塊生成了一個(gè)新的 JSON 令牌,該令牌已分配給 jwt 變量。認(rèn)證部分沒(méi)問(wèn)題。如果我們嘗試訪(fǎng)問(wèn)受限端點(diǎn)怎么辦?我們?nèi)绾卧O(shè)法訪(fǎng)問(wèn)該端點(diǎn)?

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
      });
    }
  });
?

當(dāng)您向 /me 發(fā)出 GET 請(qǐng)求時(shí),您將獲得當(dāng)前用戶(hù)信息,但為了繼續(xù)請(qǐng)求的端點(diǎn),確保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ù)中,攔截請(qǐng)求頭,并提取authorization頭。如果此標(biāo)頭中存在承載令牌,則該令牌將分配給 req.token 以便在整個(gè)請(qǐng)求中使用,并且可以使用 next( )。如果令牌不存在,您將收到 403(禁止)響應(yīng)。讓我們回到處理程序 /me,并使用 req.token 使用此令牌獲取用戶(hù)數(shù)據(jù)。每當(dāng)您創(chuàng)建新用戶(hù)時(shí),都會(huì)生成一個(gè)令牌并將其保存在數(shù)據(jù)庫(kù)的用戶(hù)模型中。這些令牌是獨(dú)一無(wú)二的。

對(duì)于這個(gè)簡(jiǎn)單的項(xiàng)目,我們只有三個(gè)處理程序。之后,您將看到:

process.on('uncaughtException', function(err) {
    console.log(err);
});
?

如果發(fā)生錯(cuò)誤,Node.js 應(yīng)用程序可能會(huì)崩潰。使用上面的代碼,可以防止崩潰,并在控制臺(tái)中打印錯(cuò)誤日志。最后,我們可以使用以下代碼片段啟動(dòng)服務(wù)器。

// Start Server
app.listen(port, function () {
    console.log( "Express server listening on port " + port);
});
?

總結(jié)一下:

  • 模塊已導(dǎo)入。
  • 配置已完成。
  • 已定義請(qǐng)求處理程序。
  • 定義中間件是為了攔截受限端點(diǎn)。
  • 服務(wù)器已啟動(dòng)。

我們已經(jīng)完成了后端服務(wù)。為了讓多個(gè)客戶(hù)端可以使用它,您可以將這個(gè)簡(jiǎn)單的服務(wù)器應(yīng)用程序部署到您的服務(wù)器上,或者也可以部署在 Heroku 中。項(xiàng)目根文件夾中有一個(gè)名為 Procfile 的文件。讓我們?cè)?Heroku 中部署我們的服務(wù)。

Heroku 部署

您可以從此 GitHub 存儲(chǔ)庫(kù)克隆后端項(xiàng)目。

我不會(huì)討論如何在 Heroku 中創(chuàng)建應(yīng)用程序;如果您之前沒(méi)有創(chuàng)建過(guò) Heroku 應(yīng)用程序,可以參考這篇文章來(lái)創(chuàng)建 Heroku 應(yīng)用程序。創(chuàng)建 Heroku 應(yīng)用程序后,您可以使用以下命令將目標(biāo)添加到當(dāng)前項(xiàng)目:

git remote add heroku <your_heroku_git_url>

現(xiàn)在您已經(jīng)克隆了一個(gè)項(xiàng)目并添加了一個(gè)目標(biāo)。在 git addgit commit 之后,您可以通過(guò)執(zhí)行 git push heroku master 將代碼推送到 Heroku。當(dāng)您成功推送項(xiàng)目時(shí),Heroku 將執(zhí)行 npm install 命令將依賴(lài)項(xiàng)下載到 Heroku 上的 temp 文件夾中。之后,它將啟動(dòng)您的應(yīng)用程序,您可以使用 HTTP 協(xié)議訪(fǎng)問(wèn)您的服務(wù)。

基于令牌的-auth-frontend

在前端項(xiàng)目中,您將看到一個(gè) Angular 項(xiàng)目。在這里,我只提及前端項(xiàng)目中的主要部分,因?yàn)?Angular 不是一個(gè)教程可以涵蓋的內(nèi)容。

您可以從此 GitHub 存儲(chǔ)庫(kù)克隆該項(xiàng)目。在此項(xiàng)目中,您將看到以下文件夾結(jié)構(gòu):

使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證

我們擁有三個(gè)組件——注冊(cè)、配置文件和登錄——以及一個(gè)身份驗(yàn)證服務(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>?定義各個(gè)組件的路由。

auth.service.ts 文件中,我們定義 AuthService 類(lèi),該類(lèi)通過(guò) API 調(diào)用來(lái)處理身份驗(yàn)證,以登錄、驗(yàn)證 Node.js 應(yīng)用程序的 API 端點(diǎn)。

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 請(qǐng)求并對(duì)用戶(hù)進(jìn)行身份驗(yàn)證。從響應(yīng)中,我們提取令牌并將其存儲(chǔ)在服務(wù)的 this.token 屬性和瀏覽器的 localStorage 中,然后將響應(yīng)作為 Observable 返回。

profile() 方法中,我們通過(guò)在 Authorization 標(biāo)頭中包含令牌來(lái)發(fā)出 GET 請(qǐng)求以獲取用戶(hù)詳細(xì)信息。

createHeaders() 方法在發(fā)出經(jīng)過(guò)身份驗(yàn)證的 API 請(qǐng)求時(shí)創(chuàng)建包含身份驗(yàn)證令牌的 HTTP 標(biāo)頭。當(dāng)用戶(hù)擁有有效令牌時(shí),它會(huì)添加一個(gè)授權(quán)標(biāo)頭。該令牌允許后端 API 對(duì)用戶(hù)進(jìn)行身份驗(yàn)證。

如果身份驗(yàn)證成功,用戶(hù)令牌將存儲(chǔ)在本地存儲(chǔ)中以供后續(xù)請(qǐng)求使用。該令牌也可供所有組件使用。如果身份驗(yàn)證失敗,我們會(huì)顯示一條錯(cuò)誤消息。

不要忘記將服務(wù) URL 放入上面代碼中的 baseUrl 中。當(dāng)您將服務(wù)部署到 Heroku 時(shí),您將獲得類(lèi)似 appname.herokuapp.com 的服務(wù) URL。在上面的代碼中,您將設(shè)置 var baseUrl = "appname.herokuapp.com"。

注銷(xiāo)功能從本地存儲(chǔ)中刪除令牌。

signup.component.ts 文件中,我們實(shí)現(xiàn)了 signup () 方法,該方法獲取用戶(hù)提交的電子郵件和密碼并創(chuàng)建一個(gè)新用戶(hù)。

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 文件看起來(lái)與注冊(cè)組件類(lèi)似。 ?
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);
      }
    );
  }
}

配置文件組件使用用戶(hù)令牌來(lái)獲取用戶(hù)的詳細(xì)信息。每當(dāng)您向后端的服務(wù)發(fā)出請(qǐng)求時(shí),都需要將此令牌放入標(biāo)頭中。 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');
      }
    );
  }
?

在上面的代碼中,每個(gè)請(qǐng)求都會(huì)被攔截,并在標(biāo)頭中放入授權(quán)標(biāo)頭和值。然后,我們將用戶(hù)詳細(xì)信息傳遞到 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>

最后,我們?cè)?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 { }
?

從上面的代碼中您可以很容易地理解,當(dāng)您轉(zhuǎn)到/時(shí),將呈現(xiàn)app.component.html頁(yè)面。另一個(gè)例子:如果您轉(zhuǎn)到/signup,則會(huì)呈現(xiàn)signup.component.html。這個(gè)渲染操作將在瀏覽器中完成,而不是在服務(wù)器端。

結(jié)論

基于令牌的身份驗(yàn)證系統(tǒng)可幫助您在開(kāi)發(fā)獨(dú)立于客戶(hù)端的服務(wù)時(shí)構(gòu)建身份驗(yàn)證/授權(quán)系統(tǒng)。通過(guò)使用這項(xiàng)技術(shù),您將只需專(zhuān)注于您的服務(wù)(或 API)。

身份驗(yàn)證/授權(quán)部分將由基于令牌的身份驗(yàn)證系統(tǒng)作為服務(wù)前面的一層進(jìn)行處理。您可以從任何客戶(hù)端(例如網(wǎng)絡(luò)瀏覽器、Android、iOS 或桌面客戶(hù)端)訪(fǎng)問(wèn)和使用服務(wù)。

以上是使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證的詳細(xì)內(nèi)容。更多信息請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線(xiàn)人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開(kāi)發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)代碼編輯軟件(SublimeText3)

熱門(mén)話(huà)題

Laravel 教程
1601
29
PHP教程
1502
276
如何在Ubuntu 24.04上安裝Angular 如何在Ubuntu 24.04上安裝Angular Mar 23, 2024 pm 12:20 PM

Angular.js是一種可自由訪(fǎng)問(wèn)的JavaScript平臺(tái),用于創(chuàng)建動(dòng)態(tài)應(yīng)用程序。它允許您通過(guò)擴(kuò)展HTML的語(yǔ)法作為模板語(yǔ)言,以快速、清晰地表示應(yīng)用程序的各個(gè)方面。Angular.js提供了一系列工具,可幫助您編寫(xiě)、更新和測(cè)試代碼。此外,它還提供了許多功能,如路由和表單管理。本指南將討論在Ubuntu24上安裝Angular的方法。首先,您需要安裝Node.js。Node.js是一個(gè)基于ChromeV8引擎的JavaScript運(yùn)行環(huán)境,可讓您在服務(wù)器端運(yùn)行JavaScript代碼。要在Ub

如何在Safari中禁用隱私瀏覽身份驗(yàn)證:iOS 17的操作指南 如何在Safari中禁用隱私瀏覽身份驗(yàn)證:iOS 17的操作指南 Sep 11, 2023 pm 06:37 PM

在iOS17中,Apple在其移動(dòng)操作系統(tǒng)中引入了幾項(xiàng)新的隱私和安全功能,其中之一是能夠要求對(duì)Safari中的隱私瀏覽選項(xiàng)卡進(jìn)行二次身份驗(yàn)證。以下是它的工作原理以及如何將其關(guān)閉。在運(yùn)行iOS17或iPadOS17的iPhone或iPad上,如果您在Safari中打開(kāi)了任何“隱私瀏覽”選項(xiàng)卡,然后退出會(huì)話(huà)或應(yīng)用程序,Apple的瀏覽器現(xiàn)在需要面容ID/TouchID身份驗(yàn)證或密碼才能再次訪(fǎng)問(wèn)它們。換句話(huà)說(shuō),如果有人在解鎖您的iPhone或iPad時(shí)拿到了它,他們?nèi)匀粺o(wú)法在不知道您的密碼的情況下查看

如何在PHP中實(shí)現(xiàn)單點(diǎn)登錄 如何在PHP中實(shí)現(xiàn)單點(diǎn)登錄 Jun 11, 2023 pm 07:01 PM

單點(diǎn)登錄(SSO)是一種身份驗(yàn)證機(jī)制,它允許用戶(hù)使用一組憑據(jù)(如用戶(hù)名和密碼)在多個(gè)應(yīng)用程序和站點(diǎn)中進(jìn)行身份驗(yàn)證。這種機(jī)制可以提高用戶(hù)的體驗(yàn)和效率,同時(shí)也增強(qiáng)了安全性。在PHP中,實(shí)現(xiàn)單點(diǎn)登錄需要采取一些特定的方法。下面我們將介紹如何在PHP中實(shí)現(xiàn)單點(diǎn)登錄。我們將分為以下幾個(gè)步驟:創(chuàng)建用戶(hù)認(rèn)證中心(AuthenticationCenter)使用OAuth2

Pi Node教學(xué):什么是Pi節(jié)點(diǎn)?如何安裝和設(shè)定Pi Node? Pi Node教學(xué):什么是Pi節(jié)點(diǎn)?如何安裝和設(shè)定Pi Node? Mar 05, 2025 pm 05:57 PM

PiNetwork節(jié)點(diǎn)詳解及安裝指南本文將詳細(xì)介紹PiNetwork生態(tài)系統(tǒng)中的關(guān)鍵角色——Pi節(jié)點(diǎn),并提供安裝和配置的完整步驟。Pi節(jié)點(diǎn)在PiNetwork區(qū)塊鏈測(cè)試網(wǎng)推出后,成為眾多先鋒積極參與測(cè)試的重要環(huán)節(jié),為即將到來(lái)的主網(wǎng)發(fā)布做準(zhǔn)備。如果您還不了解PiNetwork,請(qǐng)參考Pi幣是什么?上市價(jià)格多少?Pi用途、挖礦及安全性分析。什么是PiNetwork?PiNetwork項(xiàng)目始于2019年,擁有其專(zhuān)屬加密貨幣Pi幣。該項(xiàng)目旨在創(chuàng)建一個(gè)人人可參與

使用Slim框架中的中間件實(shí)現(xiàn)用戶(hù)身份驗(yàn)證 使用Slim框架中的中間件實(shí)現(xiàn)用戶(hù)身份驗(yàn)證 Jul 29, 2023 am 10:22 AM

使用Slim框架中的中間件實(shí)現(xiàn)用戶(hù)身份驗(yàn)證隨著Web應(yīng)用程序的發(fā)展,用戶(hù)身份驗(yàn)證成為了一個(gè)至關(guān)重要的功能。為了保護(hù)用戶(hù)的個(gè)人信息和敏感數(shù)據(jù),我們需要一種可靠的方法來(lái)驗(yàn)證用戶(hù)的身份。在本文中,我們將介紹如何使用Slim框架的中間件來(lái)實(shí)現(xiàn)用戶(hù)身份驗(yàn)證。Slim框架是一個(gè)輕量級(jí)的PHP框架,它提供了一種簡(jiǎn)單、快速的方式來(lái)構(gòu)建Web應(yīng)用程序。其中一個(gè)強(qiáng)大的特性是中間

使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證 使用Angular和Node進(jìn)行基于令牌的身份驗(yàn)證 Sep 01, 2023 pm 02:01 PM

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

Angular組件及其顯示屬性:了解非block默認(rèn)值 Angular組件及其顯示屬性:了解非block默認(rèn)值 Mar 15, 2024 pm 04:51 PM

Angular框架中組件的默認(rèn)顯示行為不是塊級(jí)元素。這種設(shè)計(jì)選擇促進(jìn)了組件樣式的封裝,并鼓勵(lì)開(kāi)發(fā)人員有意識(shí)地定義每個(gè)組件的顯示方式。通過(guò)顯式設(shè)置CSS屬性 display,Angular組件的顯示可以完全控制,從而實(shí)現(xiàn)所需的布局和響應(yīng)能力。

Beego中使用JWT實(shí)現(xiàn)身份驗(yàn)證 Beego中使用JWT實(shí)現(xiàn)身份驗(yàn)證 Jun 22, 2023 pm 12:44 PM

隨著互聯(lián)網(wǎng)和移動(dòng)互聯(lián)網(wǎng)的飛速發(fā)展,越來(lái)越多的應(yīng)用需要進(jìn)行身份驗(yàn)證和權(quán)限控制,而JWT(JSONWebToken)作為一種輕量級(jí)的身份驗(yàn)證和授權(quán)機(jī)制,在WEB應(yīng)用中被廣泛應(yīng)用。Beego是一款基于Go語(yǔ)言的MVC框架,具有高效、簡(jiǎn)潔、可擴(kuò)展等優(yōu)點(diǎn),本文將介紹如何在Beego中使用JWT實(shí)現(xiàn)身份驗(yàn)證。一、JWT簡(jiǎn)介JSONWebToken(JWT)是一種

See all articles