Zero, article directory
Nodejs 7. Identity authentication
1. Web development model
(1) Current mainstream Web development models
- Based on the traditional web development model of
服务端渲染
- New Web development model based on
前后端分离
(2) Server-side rendering Web development model
- The HTML page sent by the server to the client is dynamically generated by concatenating strings on the server.
- The client does not need to use technologies such as Ajax to additionally request page data.
(3) Advantages and disadvantages of server-side rendering
- advantage
前端耗时少
: Because the server side is responsible for dynamically generating HTML content, the browser only needs to render the page directly.有利于SEO
: Because the server responds to the complete HTML page content, it is easier for crawlers to crawl and obtain information, which is more conducive to SEO.
- shortcoming
占用服务器端资源
: That is, the server completes the splicing of HTML page content. If there are many requests, it will put a certain amount of access pressure on the server.不利于前后端分离,开发效率低
: If server-side rendering is used,无法进行分工合作
, especially for前端复杂度高
projects, is not conducive to efficient project development.
(4) Web development model with front-end and back-end separation
- The development model that separates the front and back ends,
依赖于 Ajax 技术的广泛应用
. - The Web development model that separates the front and back ends is the development model of
后端只负责提供 API 接口,前端使用 Ajax 调用接口
.
(5) Advantages and disadvantages of front-end and back-end separation
-
advantage
开发体验好
: The front-end focuses on the development of UI pages, and the back-end focuses on the development of APIs, and the front-end has more options.用户体验好
: The extensive application of Ajax technology has greatly improved the user experience and can easily achieve partial refresh of the page.减轻了服务器端的渲染压力
: Because the page is ultimately generated in each user's browser.
-
shortcoming
不利于 SEO
: Because the complete HTML page needs to be dynamically spliced on the client, the crawler cannot crawl the effective information of the page. (Solution: Using theSSR
(server side render) technology of front-end frameworks such as Vue and React can solve SEO problems very well!)
(6) How to choose a Web development model
不谈业务场景而盲目选择使用何种开发模式都是耍流氓
。- For example, if an enterprise-level website’s main function is display without complex interactions, and requires good SEO, then we need to use server-side rendering;
- For similar back-end management projects, which are highly interactive and do not need to consider SEO, you can use a development model that separates the front and back ends.
- The specific development model to be used is not absolute. In order to
同时兼顾了首页的渲染速度和前后端分离的开发效率
, some websites adopt a development model of first-screen server-side rendering + front-end and back-end separation for other pages.
2. Identity authentication
(1) What is identity authentication?
身份认证
(Authentication), also known as "identity verification" and "authentication", refers to通过一定的手段,完成对用户身份的确认
.- In Web development, user identity authentication is also involved, such as:
手机验证码登录、邮箱密码登录、二维码登录
of major websites, etc.
(2) Why identity authentication is needed
- The purpose of identity authentication is for
确认当前所声称为某种身份的用户,确实是所声称的用户
. For example, if you go to the courier to pick up the express delivery, how do you prove that the express delivery is yours. - In the development of Internet projects, how to authenticate users' identities is an issue worthy of in-depth discussion. For example, how can we ensure that the website will not mistakenly display "Jack Ma's deposit amount" to "Ma Huateng's account".
(3) Identity authentication under different development modes
服务端渲染
Recommended UseSession 认证机制
前后端分离
Recommended UseJWT 认证机制
3. Session authentication mechanism
(1) Stateless nature of HTTP protocol
- The stateless nature of the HTTP protocol refers to the client's
每次 HTTP 请求都是独立的
. There is no direct relationship between multiple consecutive requests,服务器不会主动保留每次 HTTP 请求的状态
.
(2) How to break through the stateless limitations of HTTP
- For supermarkets, in order to facilitate the cashier to give discounts to VIP users during settlement, the supermarket can issue
会员卡
to each VIP user. - The technical term in web development is
Cookie
.
(3) What are cookies?
- Cookie is
存储在用户浏览器中的一段不超过 4 KB 的字符串
. It consists of one名称(Name)、一个值(Value)
and several other有效期、安全性、使用范围的可选属性
for control cookies. 不同域名下的 Cookie 各自独立
, whenever the client initiates a request,自动
will当前域名下
all未过期的 Cookie
together< a i=4>.发送到服务器
- Several major characteristics of cookies:
- auto delivery
- Domain name independent
- Expiration time
- 4KB limit
(4) The role of cookies in identity authentication
- When the client requests the server for the first time, the server sends a to the client through
响应头的形式
, and the client will automatically .身份认证的 Cookie
将 Cookie 保存在浏览器中
- Subsequently, when the client browser
每次请求服务器的时候
, the browser will自动
pass the identity authentication related informationCookie
through请求头的形式
Send it to the server, and the server can验明客户端的身份
.
(5) Cookies are not secure
- Since
Cookie 是存储在浏览器
, and浏览器也提供了读写 Cookie 的 API
, thereforeCookie 很容易被伪造
, is not safe. - It is not recommended that the server sends important private data to the browser in the form of cookies. For example, the user’s identity information, password, etc.
(6) Improve the security of identity authentication
- In order
防止客户伪造会员卡
, the cashier can do this at the cash register after getting the membership card presented by the customer刷卡认证
. Only membership cards confirmed by the cash register to exist can be used normally. - This "
会员卡 + 刷卡认证
" design concept is the essence ofSession 认证机制
.
(7) Working principle of Session
4. Use Session authentication in Express
(1) Install express-session middleware
- In the Express project, you only need to install the express-session middleware to use Session authentication in the project:
npm install express-session
(2) Configure express-session middleware
- After the express-session middleware is successfully installed, you need to register the session middleware through
app.use()
. The sample code is as follows:
// 导入 session 中间件
const session = require('express-session')
// 配置 session 中间件
app.use(
session({
secret: 'keytest', //secret属性值可以是任意字符串
resave: false,
saveUninitialized: true,
})
)
(3) Store data in session
- After the express-session middleware is successfully configured, you can access and use the session object through
req.session
to store the user's key information:
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) Get data from session
- can directly obtain previously stored data from the
req.session
object. The sample code is as follows:
// 获取用户姓名的接口
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) Clear session
- Call the
req.session.destroy()
function to clear the session information saved by the server.
// 退出登录的接口
app.post('/api/logout', (req, res) => {
//清空 Session 信息
req.session.destroy()
res.send({
status: 0,
msg: '退出登录成功',
})
})
5. JWT authentication mechanism
(1) Limitations of Session authentication
- Required for Session authentication mechanism
配合 Cookie 才能实现
. Since cookies do not support cross-domain access by default, cross-domain session authentication can only be achieved when前端跨域请求后端接口
is involved.需要做很多额外的配置
is required. - When the front end requests the backend interface
不存在跨域问题
,推荐使用 Session
identity authentication mechanism. - When the front-end needs to request the back-end interface across domains, it is not recommended to use the Session authentication mechanism, and it is recommended to use the JWT authentication mechanism.
(2) What is JWT
- JWT (English full name: JSON Web Token) is currently.
最流行
跨域认证解决方案
(3) How JWT works
- The user's information is stored in the client browser in the form of a Token string. The server authenticates the user's identity by restoring the Token string.
(4) Components of JWT
- JWT usually consists of three parts, namely
Header(头部)、Payload(有效荷载)、Signature(签名)
. - The three are separated by English
.
, the format is as follows:
- Here is an example of a JWT string:
(5) Meaning of JWT components
Payload
: Real user information, which is a string generated after encrypting user information.Header 和 Signature
: The part of安全性相关
is just to ensure the security of Token
(6) How to use JWT
- After the client receives the JWT returned from the server, it usually stores it in
localStorage
orsessionStorage
. - After that, every time the client communicates with the server, it must bring this JWT string for identity authentication. The recommended approach is to place the JWT in the field of
HTTP 请求头
in the following format:Authorization
6. Using JWT in Express
(1) Install JWT related packages
-
Install two JWT related packages:
npm install jsonwebtoken express-jwt
-
jsonwebtoken
: Generate JWT string -
express-jwt
: Parse JWT string and restore it to JSON object
-
(2) Import JWT related packages
- Use the
require()
function to import the two JWT-related packages:
// 生成 JWT 字符串
const jwt = require('jsonwebtoken')
// 将 JWT 字符串解析还原成 JSON 对象
const expressJWT = require('express-jwt')
(3) Define secret key
- In order
保证 JWT 字符串的安全性
to prevent the JWT string from being cracked by others during network transmission, we need to specifically define one for加密
and Secret key of解密
:- When generating a JWT string, you need to use
secret 密钥
to perform加密
on the user's information, and finally get the encrypted JWT string - When parsing and restoring the JWT string to a JSON object, you need to use
secret 密钥
解密
- When generating a JWT string, you need to use
// secret密钥的本质:就是一个字符串
const secretKey = 'mysecret'
(4) Generate JWT string after successful login
- Call the method provided by the
jsonwebtoken
package to encrypt the user's information into a JWT string and respond to the client:sign()
// 登录接口
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) Restore JWT string to JSON object
- Every time the client accesses those authorized interfaces, it needs to actively send the Token string to the server for identity authentication through
请求头中的 Authorization 字段
. - At this time, the server can automatically parse and restore the Token sent by the client into a JSON object through the
express-jwt
middleware:
// 使用app.use() 来注册中间件
// expressJWT(secret:secretKey})就是用来解断Token的中间件
// .unless({path:[/A\/api\//]})用来指定哪些接口不需要方问权限
app.use(expressJWT({
secret: secretKey }).unless({
path: [/^\/api\//] }))
(6) Use req.user to obtain user information
- When
express-jwt
this middleware is successfully configured, you can use thereq.user
object in those interfaces with permissions to access the JWT string The user information parsed from , the sample code is as follows:
// 这是一个有权限的 API 接口
app.get('/admin/getinfo', function(req, res) {
console.log(req.user)
res.send({
status: 200,
message: '获取用户信息成功!',
data: req.user, // 要发送给客户端的用户信息
})
})
(7) Capture errors generated after failure to parse JWT
- When using express-jwt to parse the Token string, if the Token string sent by the client is
过期
or不合法
, a will be generated. The error of a>解析失败
affects the normal operation of the project. - We can capture this error and perform related processing through
Express 的错误中间件
. The sample code is as follows:
// 使用全局错误处理中间件,捕获解析 JWT 失败后产生的错误
app.use((err, req, res, next) => {
// 这次错误是由 token 解析失败导致的
if (err.name === 'UnauthorizedError') {
return res.send({
status: 401,
message: '无效的token',
})
}
res.send({
status: 500,
message: '未知的错误',
})
})