ゼロ、記事ディレクトリ
Nodejs 7. ID 認証
1. Web開発モデル
(1) 現在主流の Web 開発モデル
服务端渲染
の従来の Web 開発モデルに基づいています前后端分离
に基づく新しい Web 開発モデル
(2) サーバーサイドレンダリングWeb開発モデル
- サーバーからクライアントに送信される HTML ページは、サーバー上で文字列を連結することによって動的に生成されます。
- クライアントは、追加のページ データを要求するために Ajax などのテクノロジを使用する必要はありません。
(3) サーバーサイドレンダリングのメリットとデメリット
- アドバンテージ
前端耗时少
: サーバー側は HTML コンテンツを動的に生成する役割を担うため、ブラウザーはページを直接レンダリングするだけで済みます。有利于SEO
: サーバーは HTML ページのコンテンツ全体に応答するため、クローラーがクロールして情報を取得しやすくなり、SEO に有利になります。
- 欠点がある
占用服务器端资源
: つまり、サーバーは HTML ページのコンテンツの結合を完了しますが、リクエストが多数ある場合は、サーバーに一定のアクセス圧力がかかります。不利于前后端分离,开发效率低
: サーバー側レンダリングを使用する場合、无法进行分工合作
、特に前端复杂度高
プロジェクトの場合、効率的なプロジェクト開発には役立ちません。
(4) フロントエンドとバックエンドを分離した Web 開発モデル
- フロントエンドとバックエンドを分離する開発モデル
依赖于 Ajax 技术的广泛应用
。 - フロントエンドとバックエンドを分離する Web 開発モデルは
后端只负责提供 API 接口,前端使用 Ajax 调用接口
の開発モデルです。
(5) フロントエンドとバックエンド分離のメリットとデメリット
-
アドバンテージ
开发体验好
: フロントエンドは UI ページの開発に重点を置き、バックエンドは API の開発に重点を置き、フロントエンドにはより多くのオプションがあります。用户体验好
: Ajax テクノロジーの広範な適用により、ユーザー エクスペリエンスが大幅に向上し、ページの部分更新を簡単に実現できます。减轻了服务器端的渲染压力
:ページは最終的に各ユーザーのブラウザで生成されるためです。
-
欠点がある
不利于 SEO
: 完全な HTML ページをクライアント上で動的に結合する必要があるため、クローラーはページの有効な情報をクロールできません。 (解決策: Vue や React などのフロントエンド フレームワークのSSR
(サーバー サイド レンダー) テクノロジーを使用すると、SEO の問題をうまく解決できます。)
(6) Web開発モデルの選び方
不谈业务场景而盲目选择使用何种开发模式都是耍流氓
。- たとえば、エンタープライズ レベルの Web サイトの主な機能が複雑なインタラクションを行わずに表示することであり、優れた SEO が必要な場合は、サーバー側レンダリングを使用する必要があります。
- 高度にインタラクティブで SEO を考慮する必要がない同様のバックエンド管理プロジェクトの場合は、フロントエンドとバックエンドを分離する開発モデルを使用できます。
- 使用される特定の開発モデルは絶対的なものではありません。
同时兼顾了首页的渲染速度和前后端分离的开发效率
するために、一部の Web サイトでは、ファースト スクリーンのサーバー側レンダリング + フロントエンドとバックの開発モデルを採用しています。他のページの分割を終了します。
2.本人認証
(1)本人認証とは何ですか?
身份认证
(認証) は、「本人確認」および「認証」とも呼ばれ、通过一定的手段,完成对用户身份的确认
を指します。- Web 開発では、次のようなユーザー ID 認証も関係します。
手机验证码登录、邮箱密码登录、二维码登录
主要な Web サイトなど。
(2) なぜ本人認証が必要なのか
- ID 認証の目的は
确认当前所声称为某种身份的用户,确实是所声称的用户
です。たとえば、速達便を受け取りに宅配業者に行った場合、その速達便が自分のものであることをどのように証明しますか。 - インターネット プロジェクトの開発において、ユーザーの身元をどのように認証するかは、徹底的に議論する価値のある問題です。たとえば、ウェブサイトに「ジャック・マーの入金額」が「馬化騰の口座」と誤って表示されないようにするにはどうすればよいでしょうか。
(3) 異なる開発モードでの本人認証
服务端渲染
推奨される使用方法Session 认证机制
前后端分离
推奨される使用方法JWT 认证机制
3. セッション認証メカニズム
(1) HTTPプロトコルのステートレス性
- HTTP プロトコルのステートレスな性質は、クライアントの
每次 HTTP 请求都是独立的
を指します。複数の連続するリクエストの間に直接の関係はありません、服务器不会主动保留每次 HTTP 请求的状态
。
(2) HTTPのステートレス限界を突破する方法
- スーパーマーケットの場合、レジ担当者が決済時に VIP ユーザーに割引を提供しやすくするために、スーパーマーケットは各 VIP ユーザーに
会员卡
を発行できます。 - Web 開発の専門用語は
Cookie
です。
(3) クッキーとは何ですか?
- Cookie は
存储在用户浏览器中的一段不超过 4 KB 的字符串
です。これは、コントロール Cookie として 1 つの名称(Name)、一个值(Value)
と他のいくつかの有效期、安全性、使用范围的可选属性
で構成されます。 不同域名下的 Cookie 各自独立
では、クライアントがリクエストを開始するたびに、自动
は当前域名下
すべて未过期的 Cookie
一緒< a i= 4>。发送到服务器
- Cookie の主な特徴は次のとおりです。
- 自動配信
- ドメイン名に依存しない
- 有効期限
- 4KB制限
(4) 本人認証におけるCookieの役割
- クライアントが初めてサーバーをリクエストすると、サーバーは
响应头的形式
を通じて身份认证的 Cookie
をクライアントに送信し、クライアントは自動的に を送信します。 a>将 Cookie 保存在浏览器中
。 - その後、クライアントのブラウザが
每次请求服务器的时候
、ブラウザは自动
ID 認証関連情報をCookie
渡します。 /span>できます。请求头的形式
それをサーバーに送信すると、サーバーは验明客户端的身份
(5) Cookie は安全ではありません
Cookie 是存储在浏览器
と浏览器也提供了读写 Cookie 的 API
、つまりCookie 很容易被伪造
は安全ではありません。- サーバーが重要な個人データを Cookie の形式でブラウザに送信することはお勧めできません。たとえば、ユーザーの身元情報やパスワードなどです。
(6)本人認証の安全性向上
- 順番
防止客户伪造会员卡
、レジ担当者は顧客から提示された会員カードを受け取った後、レジでこれを行うことができます刷卡认证
。レジにて存在が確認された会員カードのみが通常通りご利用いただけます。 - この「
会员卡 + 刷卡认证
」の設計コンセプトがSession 认证机制
の本質です。
(7) セッションの動作原理
4. Express でセッション認証を使用する
(1) Express-Sessionミドルウェアのインストール
- Express プロジェクトでは、プロジェクトでセッション認証を使用するために Express-session ミドルウェアをインストールするだけで済みます。
npm install express-session
(2) Express-Sessionミドルウェアの構成
- エクスプレス セッション ミドルウェアが正常にインストールされたら、
app.use()
を通じてセッション ミドルウェアを登録する必要があります。サンプル コードは次のとおりです。
// 导入 session 中间件
const session = require('express-session')
// 配置 session 中间件
app.use(
session({
secret: 'keytest', //secret属性值可以是任意字符串
resave: false,
saveUninitialized: true,
})
)
(3) データをセッションに保存する
- エクスプレス セッション ミドルウェアが正常に構成されたら、
req.session
を通じてセッション オブジェクトにアクセスして使用し、ユーザーのキー情報を保存できます。
app.post('/api/login', (req, res) => {
// 判断用户提交的登录信息是否正确
if (req.body.username !== 'admin' || req.body.password !== '000000') {
return res.send({
status: 1, msg: '登录失败' })
}
// 注意:只有成功配置了 express-session 这个中间件之后,才能够通过 req 点出来 session 这个属性
req.session.user = req.body // 用户的信息存储到session中
req.session.islogin = true // 用户的登录状态存储到session中
res.send({
status: 0, msg: '登录成功' })
})
(4) セッションからデータを取得する
- は、
req.session
オブジェクトから以前に保存されたデータを直接取得できます。サンプル コードは次のとおりです:
// 获取用户姓名的接口
app.get('/api/username', (req, res) => {
//判断用户是否登录
if (!req.session.islogin) {
return res.send({
status: 1, msg: 'fail' })
}
res.send({
status: 0,
msg: 'success',
username: req.session.user.username,
})
})
(5) セッションをクリアする
req.session.destroy()
関数を呼び出して、サーバーによって保存されたセッション情報をクリアします。
// 退出登录的接口
app.post('/api/logout', (req, res) => {
//清空 Session 信息
req.session.destroy()
res.send({
status: 0,
msg: '退出登录成功',
})
})
5. JWT認証メカニズム
(1) セッション認証の制限事項
- セッション認証メカニズムに必須
配合 Cookie 才能实现
。デフォルトでは Cookie はクロスドメイン アクセスをサポートしていないため、クロスドメイン セッション認証は前端跨域请求后端接口
が関与する場合にのみ実現できます。需要做很多额外的配置
が必要です。 - フロントエンドがバックエンド インターフェースをリクエストするとき
不存在跨域问题
、推荐使用 Session
ID 認証メカニズム。 - フロントエンドがドメインを越えてバックエンド インターフェイスを要求する必要がある場合、セッション認証メカニズムを使用することはお勧めできません。JWT 認証メカニズムを使用することをお勧めします。
(2) JWTとは
- JWT (英語の完全名: JSON Web Token) は現在です。
最流行
跨域认证解决方案
(3) JWTの仕組み
- ユーザーの情報は、トークン文字列の形式でクライアント ブラウザに保存されます。サーバーはトークン文字列を復元することでユーザーの ID を認証します。
(4) JWTの構成要素
- JWT は通常、
Header(头部)、Payload(有效荷载)、Signature(签名)
という 3 つの部分で構成されます。 - 3 つは英語で区切られています
.
。形式は次のとおりです:
- JWT 文字列の例を次に示します。
(5) JWTコンポーネントの意味
Payload
: 実際のユーザー情報。ユーザー情報を暗号化して生成された文字列です。Header 和 Signature
:安全性相关
の部分は、トークン のセキュリティを確保するだけです。
(6) JWTの使い方
- クライアントは、サーバーから返された JWT を受信すると、通常、
localStorage
またはsessionStorage
に保存します。 - その後、クライアントはサーバーと通信するたびに、ID 認証のためにこの JWT 文字列を取得する必要があります。推奨されるアプローチは、JWT を
HTTP 请求头
のAuthorization
フィールドに次の形式で配置することです。
6. Express での JWT の使用
(1) JWT関連パッケージのインストール
-
2 つの JWT 関連パッケージをインストールします。
npm install jsonwebtoken express-jwt
-
jsonwebtoken
: JWT文字列を生成します -
express-jwt
: JWT文字列を解析してJSONオブジェクトに復元します
-
(2) JWT関連パッケージのインポート
require()
関数を使用して、2 つの JWT 関連パッケージをインポートします。
// 生成 JWT 字符串
const jwt = require('jsonwebtoken')
// 将 JWT 字符串解析还原成 JSON 对象
const expressJWT = require('express-jwt')
(3) 秘密鍵を定義する
- ネットワーク送信中に JWT 文字列が他の人によって解読されるのを防ぐ
保证 JWT 字符串的安全性
ために、加密
と解密
の秘密鍵:- JWT 文字列を生成するときは、
secret 密钥
を使用してユーザーの情報に対して加密
を実行し、最後に暗号化された JWT 文字列を取得する必要があります。 - JWT 文字列を解析して JSON オブジェクトに復元する場合は、
secret 密钥
を使用する必要があります。解密
- JWT 文字列を生成するときは、
// secret密钥的本质:就是一个字符串
const secretKey = 'mysecret'
(4) ログイン成功後にJWT文字列を生成
jsonwebtoken
パッケージで提供されるsign()
メソッドを呼び出して、ユーザーの情報を JWT 文字列に暗号化し、クライアントに応答します。
// 登录接口
app.post('/api/login', function(req, res) {
// 将 req.body 请求体中的数据,转存为 userinfo 常量
const userinfo = req.body
// 登录失败
if (userinfo.username !== 'admin' || userinfo.password !== '000000') {
return res.send({
status: 400,
message: '登录失败!',
})
}
// 登录成功
// 在登录成功之后,调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端
// 参数1:用户的信息对象
// 参数2:加密的秘钥
// 参数3:配置对象,可以配置当前 token 的有效期
// 记住:千万不要把密码加密到 token 字符中
const tokenStr = jwt.sign({
username: userinfo.username }, secretKey, {
expiresIn: '30s' })
res.send({
status: 200,
message: '登录成功!',
token: tokenStr, // 要发送给客户端的 token 字符串
})
})
(5) JWT文字列をJSONオブジェクトに復元
- クライアントは、これらの承認されたインターフェイスにアクセスするたびに、
请求头中的 Authorization 字段
を通じて ID 認証のためにトークン文字列をサーバーにアクティブに送信する必要があります。 - 現時点では、サーバーは、
express-jwt
ミドルウェアを通じて、クライアントから JSON オブジェクトに送信されたトークンを自動的に解析して復元できます。
// 使用app.use() 来注册中间件
// expressJWT(secret:secretKey})就是用来解断Token的中间件
// .unless({path:[/A\/api\//]})用来指定哪些接口不需要方问权限
app.use(expressJWT({
secret: secretKey }).unless({
path: [/^\/api\//] }))
(6) req.userを利用してユーザー情報を取得する
- このミドルウェアが正常に設定されると
express-jwt
、JWT 文字列にアクセスする権限を持つreq.user
オブジェクトをこれらのインターフェイスで使用できるようになります。 、サンプル コードは次のとおりです。
// 这是一个有权限的 API 接口
app.get('/admin/getinfo', function(req, res) {
console.log(req.user)
res.send({
status: 200,
message: '获取用户信息成功!',
data: req.user, // 要发送给客户端的用户信息
})
})
(7) JWTの解析失敗後に発生するキャプチャエラー
- express-jwt を使用してトークン文字列を解析する場合、クライアントから送信されたトークン文字列が
过期
または不合法
の場合、 a>解析失败
のエラーはプロジェクトの正常な動作に影響を与えます。 - このエラーをキャプチャし、
Express 的错误中间件
を通じて関連処理を実行できます。サンプル コードは次のとおりです。
// 使用全局错误处理中间件,捕获解析 JWT 失败后产生的错误
app.use((err, req, res, next) => {
// 这次错误是由 token 解析失败导致的
if (err.name === 'UnauthorizedError') {
return res.send({
status: 401,
message: '无效的token',
})
}
res.send({
status: 500,
message: '未知的错误',
})
})