⼀、JWT⾝份认证简介
JSON Web Token(JWT)是⽬前最流⾏的跨域⾝份验证解决⽅案,相较于session机制,服务器就不需要保存任何 session 数据了,也就是说,服务器变成⽆状态了,从⽽⽐较容易实现扩展。JWT 实际上是⼀个令牌(Token),服务器会将⼀些元数据、指定的secret进⾏签名并⽣成token,并返回给客户端,客户端得到这个服务器返回的令牌后,需要将其存储到 Cookie 或 localStorage 中,此后,每次与服务器通信都要带上这个令牌,可以把它放到 Cookie 中⾃动发送,但这样做不能跨域,所以更好的做法是将其放到 HTTP 请求头 Authorization 字段⾥⾯。⼆、JWT的使⽤
① 安装并引⼊jsonwebtoken模块;
② 对元数据、secret密钥进⾏签名,并⽣成对应的token;③ 对token进⾏校验是否过期;
const jwt = require(\"jsonwebtoken\"); // 引⼊jwt
const secret = \"this is a private key\"; // 指定⼀个⽤于⽣成token的密钥字符串
const token = jwt.sign({ foo: 'bar' }, secret, { // 传⼊元数据和secret密钥,并指定过期时间⽣成token expiresIn: 5, // 单独⼀个数字表⽰多少秒 // expiresIn: \"10h\表⽰10⼩时后过期 // expiresIn: \"2d\" // 表⽰2天后过期});
console.log(`token is ${token}`);
setTimeout(() => { // 5秒后对该token进⾏校验 jwt.verify(token, secret, (err, decoded) => { console.log(err); if (err) {
console.log('token 已经失效了.'); } else {
console.log(`token data is ${JSON.stringify(decoded)}`); } });
}, 5000);
⽣成的token为⼀个很长的字符串,分为三部分,每部分由.号隔开,即 头部.载荷.签名,5秒后token校验结果为error,即token已经过期,校验的时候,会得到token的解码数据,主要包括⽣成token时候的元数据、token的签发时间(iat)、token的过期时间(exp)
// ⽣成的token字符串为
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE1NjY3MzE4MzEsImV4cCI6MTU2NjczMTgzNn0.cZZkExNnVqBtnfQN2vtU2Z7JB0PBo1CFyC5NiOywg54// token decoded后的数据
token data is {\"foo\":\"bar\
三、封装axios
由于在使⽤jwt认证的时候,客户端向服务器发起请求的时候,都要带上token,即要获取到token并将其放到请求头的Authorization字段中,服务器才能从authorization中取出token并进⾏校验,所以我们必须通过拦截器去实现,在每次请求之前将请求进⾏拦截,然后添加上token,再继续向服务器发起请求。
import axios from \"axios\";class Request { constructor() {
this.baseURL = process.env.NODE_ENV === 'development' ? 'http://localhost:3000' : '/'; // 设置请求baseURL this.timeout = 2000; // 设置请求超时时间 }
request(config){// 这⾥的config是请求的时候传递的参数配置对象,⽐如url、method、data等 const instance = axios.create({ // 创建axios实例 baseURL: this.baseURL, timeout: this.timeout, });
// 设置拦截器
instance.interceptors.request.use((config) => { // 请求拦截之后就是要使⽤这个config, config表⽰整个请求对象
config.headers.Authorization = localStorage.getItem('token'); // 将token从localStorage中取出并添加到请求头的Authorization字段上 return config; // 返回请求对象,继续向服务器发起请求 }, err => Promise.reject(err)); // 设置响应拦截器
instance.interceptors.response.use(res => res.data, err => Promise.reject(err));
return instance(config); }}
export default new Request();
四、通过路由钩⼦进⾏登录校验
我们需要在路由跳转之前,进⾏登录校验,即校验登录的token是否已经过期,如果token没有失效,则可以继续访问页⾯;如果token已经失效,那么检查⼀下所访问的页⾯是否需要登录才能访问,如果是需要登录后才能访问,那么跳转到登录页⾯;如果是不需要登录也能访问的页⾯则继续访问;
const whiteList = [\"/\"]; // 定义⼀个⽩名单列表router.beforeEach(async (to, from, next) => {
if (whiteList.includes(to.path)) { // 如果是访问的⽩名单中的页⾯ return next(); // 不需要校验,直接返回继续访问该页⾯ }
const isTokenAvailable = await store.dispatch('validate'); // 校验token是否失效 if (isTokenAvailable) { // 如果token未失效
if(to.path === \"/login\") { // 如果访问的是login页⾯,则回到⾸页 next(\"/\");
} else { // 如果访问的不是login页⾯,则继续访问当前要访问的页⾯ next(); }
} else { // 如果token失效了
const needLogin = to.matched.some(item => item.meta.needLogin); // 检测要访问的页⾯是否需要登录才能访问 if(needLogin) { // 如果访问的页⾯是需要登录的 next(\"/login\"); // 跳转到登录页⾯
} else { // 如果访问的页⾯是不需要登录的,则直接继续访问 next(); } }});
上⾯item.meta.needLogin,这个needLogin是在router中进⾏⾃定义配置的,在配置路由的时候,允许通过meta属性配置⼀些⾃定义的元数据,如下所⽰:
export default new Router({ routes: [ {
path: '/profile', name: 'profile',
component: Profile, meta: {needLogin: true} } ]})
五、总结
jwt认证,主要就是Vue路由钩⼦beforeEach()的应⽤,以及请求拦截器的封装,在每次路由跳转前进⾏token认证(校验),检测token是否失效,其校验过程就是向服务器发起⼀个请求,⽐如\"/validate\",由于客户端请求拦截器的作⽤,会在发起\"/validate\"请求之前,在请求头的Authorization字段加上token,服务器收到token后就能对token是否有效进⾏校验了,然后返回token校验结果,客户端再根据token的校验结果进⾏路由的具体跳转。以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
因篇幅问题不能全部显示,请点此查看更多更全内容