身份认证
权限管理分为2种:
1、身份认证:是否登录,或者登录是否过期
2、权限操作:在登录成功的前体下,不同的角色有不同的权限
身份认证实现的方式:
1、后端采用session 前端采用cookie
2、后端采用jwt 前端采用本地存储
jwt
jsonwebtoken
token:临时身份认证令牌 登录成功后,后端或返回一个字符串给前端【这个字符串就称为token】,以后每次前端访问后端资源的时候就将这个令牌带着,后端就根据是否有这个令牌来判断是否进行了登录操作。
流程
- 如果未登录或者登录过期则后端接口直接报错,反之则不报错
- 登录成功—后端就生成token(是一个字符串)
- 后端保存token ,然后将token返回给前端
- 前端本地存储存储返回token
- 以后每次请求后端接口的时候将token给带上
- 后端在正式访问接口之前会对身份进行认证【取出前端发送的请求中的token,和后端进行比对】如果比对成功则放行,如果比对不成功则报401错误。
开发流程
安装插件
jsonwebtoken : 负责生成token ,解析token
express-jwt :负责拦截和校验token
定义一个密钥
appConfig.js
------
const secret = "hello";
定义一个拦截配置文件
jwtAuth.js
-------
let {expressjwt} = require("express-jwt"); //负责拦截
let {secret} = require("./appConfig")
let jwtAuth = expressjwt({
secret,
algorithms:['HS256'],
credentialsRequired:true //默认为false 只会拦截tonken过期的情况 如果为true 不仅会拦截token过期还会拦截没有token
}).unless({ //白名单 不拦截路径
path:['/users/userLogin','/users/userReg']
})
module.exports = jwtAuth;
在app.js中使用
关于认证失败
后端会返回401错误【HTTP的状态码】,意味着没有登录或者登录时间过期
前端逻辑中:跳转登录页面
定义一个401 的JS文件,然后在需要使用的页面进行引入即可
$.ajaxSetup({ //对当前页面的全局ajax进行配置
error:function(resp){
if(resp&&resp.status===401){
location.href="./login.html";
alert("请登录.....")
}
}
})
token验证
1、生成token
后端在登录接口中:
let token = jsonwebtoken.sign({user:data[0]},secret,{expiresIn:20}); //sign(需要保存的数据,秘钥,过期时间) 过期时间是一个对象{expresIn:时间--以秒为单位}
localStorage.setItem("token",resp.token); //一旦登录成功则本地保留token
2、验证token—【不需要自己去写代码】
在需要校验token的接口请求中携带token
只能在请求头中携带token,token的属性名必须为:Authorization
$.ajaxSetup({
headers:{
Authorization:localStorage.getItem("token")
},
error:function(resp){
if(resp&&resp.status===401){
location.href="./login.html";
alert("请登录.....")
}
}
})
token解析
//业务需要userId 其实一般情况是token中进行获取
let auth = req.get("Authorization");//获取请求头--根据K获取对应的值
let token = auth.split(" ")[1];
let {user} = jsonwebtoken.verify(token,secret);
跨域处理
基本概念
跨域报错:
Access-Control-Allow-Origin' header is present on the requested resource.
为什么会跨域:
浏览器的安全策略
- 同源
- 浏览器页面请求其他资源的时候,需要保证 协议 IP地址 端口号 都一致,这种情况称为同源,否则只要有一个不一样则会出现跨域
- 如
http://127.0.0.1:8080/html/login.html --前端页面
---------------
http://127.0.0.1:8080/user/login --- 不会跨域
ftp://127.0.0.1:8080/user/login --- 跨域【网络协议不一致】
http://127.0.0.1:5500/user/login --- 跨域【端口号不一致】
http://localhost:8080/user/login --- 跨域【IP地址不一致】
什么情况会跨域:
只要网络协议 IP地址 端口号中一个不一致则会出现跨域问题。
为什么需要解决跨域问题
现在主流的开发模式是前后端分离,前端和后端是完全的2个独立项目。
解决跨域问题
JSONP
resp.jsonp({code:200,msg:"请求成功"}); //后端以JSONP的形式返回
dataType:"jsonp",
CORS【掌握】
跨域资源共享:在服务端设置哪些地址哪些请求可以进行跨域
var allowCrossDomain = function (req, res, next) {
// 设置允许跨域访问的请求源(* 表示接受任意域名的请求)
res.header("Access-Control-Allow-Origin", "*");
// 设置允许跨域访问的请求头
res.header("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type,Accept,Authorization");
// 设置允许跨域访问的请求类型
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
// 同意 cookie 发送到服务器(如果要发送cookie,Access-Control-Allow-Origin 不能设置为星号)
res.header('Access-Control-Allow-Credentials', 'true');
next();
};
如果配置了跨域 ajax请求有一次预检操作
代理服务器
Nginx
前端配置代理