一.web开发模式
1.基于基于服务器端渲染的传统web开发模式
服务端渲染概念:服务器发送给客户端的HTML页面,是在服务器通过拼接字符串,动态生成的。
优点:
-
前端耗时少。
-
有利于SEO。
缺点:
-
占用服务器端资源。
-
不利于前后端分离,开发效率低。
2.基于前后端分离的web开发模式
前后端分离概念:前后端分离的开发模式,依赖于Ajax技术的广泛应用。简而言之,就是后端只负责提供API接口,前端使用Ajax调用接口的开发模式。
优点:
-
开发体验好。
-
用户体验好。
-
减轻了服务器端的渲染压力。
缺点:
不利于SEO。
3.如何进行选择
主要展示而没有复杂交互,且需要良好SEO,这时就可选择服务器端渲染。
交互性较强,需后台管理项目,不需要考虑SEO,这时就可选择前后端分离。
注:具体使用何种开发模式并不是绝对的,这两种根据具体情况也可以两者兼用。
二.身份认证
身份认证又称"身份验证"、"鉴权",是指通过一定手段,完成对用户身份的确认。
不同模式下的身份认证:
-
服务器端渲染——————Session认证机制。
-
前后端分离——————JWT认证机制。
三.Session认证机制
1.HTTP协议的无状态性
指的是客户端的每次HTTP请求都是独立的,连续多个请求之间没有直接的关系,服务器不会主动保留每次HTTP请求的状态。
2.Cookie
它是存储在用户浏览器中的一段不超过4KB的字符串。它由一个名称(Name),一个值(Value)和其它几个用于控制Cookie有效期,安全性,使用范围的可选属性组成的。
注:不同域名下Cookie各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的Cookie一同发送到服务器。
特性:
-
自动发送。
-
域名独立。
-
过期时限。
-
4KB限制。
注:Cookie不具有安全性,易被伪造,不要在其中存储重要数据。
3.在Express中使用Session认证
安装:
npm i express-session
导入:
const session = require('express-session');
用app.use()来注册session中间件:
app.use(session({
secret:'' //可以为任意字符串
reave:false //固定写法
saveUninitialized:true //固定写法
}))
配置成功后可以req.session来访问和使用session对象。
在session中存数据:
app.post('/api/login',(req,res)=>{
if(req.body.username !== 'admin' || req.body.password !== '000000'){
return res.send({status:1,msg:'登录失败!'});
}
req.session.user = req.body;//将用户信息存储到Session中
req.session.islogin = true;//将用户的登录状态存储到Session中
res.send({status:0,msg:'登录成功'});
})
在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})
})
清空session:
//调用req.session.destroy()即可
app.post('/api/logout',(req,res)=>{
req.session.destroy();
res.send({status:0,msg:'退出登录成功'});
})
四.JWT认证机制
目前最流行的跨域认证解决方案。
注:前端请求,后端接口不存在跨域问题,推荐使用Session。
1.组成部分
Header.Payload.Signature
Header:头部。(保证安全性)
Payload:有效荷载。(真正的用户信息)
Signature:签名。(保证安全性)
2.使用方式
返回的JWT通常在储存在localStorage或sessionStorage中。
方法:把JWT放在HTTP请求头的Authorization字段中。
Authorization:Bearer < token >
3.在Express中使用JWT
安装:
npm i jsonwebtoken express-jwt
导入:
const jwt = require('jsonwebtoken');
const expressJWT = =require('express-jwt')
定义密钥:
const secretkey = 'itheima No1';
调用jsonwebtoken包提供的sign()方法,将用户信息加密成token字符串,响应给客户端。
app.post('/api/login',(req,res)=>{
res.send({status:0,
msg:'登录成功',
token:jwt.sign({username:userinfo.username},secretkey,{expiresIn:'30s'})
})
})
将JWT字符串还原为JSON对象:
app.use(expressJWT({secret:secretkey}),.unless({path:[/^\/api\//]}))
使用req.user获取用户信息:
app.use('/admin/getinfo',(req,res)=>{
res.send({
status:200,
msg:'获取用户信息成功!',
data:req.user
})
})
捕获解析JWT失败后产生的错误:
app.use((err,req,res,next)=>{
if(err.name === 'UnauthorizedError'){
return res.send({status:401,msg:'无效的token'});
}
res.send({status:500,msg:'未知错误'})
})