You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vue-shop-admin-work/modules/passport.js

123 lines
10 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 引入Passport模块它是Node.js中用于处理用户认证的常用中间件可方便地集成多种认证策略
const passport = require('passport');
// 引入Passport的本地策略LocalStrategy通常用于基于用户名和密码的认证方式比如常见的表单登录验证
const LocalStrategy = require('passport-local').Strategy;
// 引入Passport的HTTP Bearer策略Strategy常用于基于令牌Token的认证比如JSON Web TokensJWT认证场景
const Strategy = require('passport-http-bearer').Strategy;
// 引入jsonwebtoken模块用于处理JSON Web TokensJWT的生成、验证等操作
var jwt = require("jsonwebtoken");
// 引入Lodash库它提供了很多实用的工具函数用于处理数据、对象等此处虽未明确体现具体使用的功能但可能用于辅助数据操作等
var _ = require('lodash');
// 引入配置模块config并获取名为"jwt_config"的配置项通常用于获取与JWT相关的配置信息如密钥、过期时间等
var jwt_config = require("config").get("jwt_config");
// 通过登录函数初始化
/**
* 初始化passport框架
* 此函数的主要作用是配置Passport的不同认证策略并将Passport初始化到给定的应用程序app
* 同时提供回调机制,方便在初始化完成后执行额外的操作。
*
* @param {[type]} app 全局应用程序通常是Express等Web框架创建的应用实例用于挂载中间件等操作。
* @param {[type]} loginFunc 登录函数,用于执行具体的用户名和密码验证逻辑,比如查询数据库验证用户输入的用户名和密码是否匹配等操作。
* @param {Function} callback 回调函数在Passport初始化及相关策略配置完成后被调用可用于执行后续自定义的初始化步骤等操作可选参数
*/
module.exports.setup = function (app, loginFunc, callback) {
// 用户名密码 登录策略
// 使用Passport的LocalStrategy配置基于用户名和密码的认证策略
passport.use(new LocalStrategy(
// 定义验证逻辑函数接收用户名、密码以及回调函数done作为参数
function (username, password, done) {
// 如果没有传入登录验证函数loginFunc则直接通过回调函数done返回错误信息表示登录验证函数未设置
if (!loginFunc) return done("登录验证函数未设置");
// 调用传入的登录验证函数loginFunc传入用户名和密码进行验证验证完成后会在回调函数中返回结果
loginFunc(username, password, function (err, user) {
// 如果验证过程中出现错误通过回调函数done返回错误信息给Passport告知认证失败原因
if (err) return done(err);
// 如果验证成功通过回调函数done返回用户信息通常是包含用户相关数据的对象给Passport表示认证成功
return done(null, user);
});
}
));
// token验证策略
// 使用Passport的HTTP Bearer策略配置基于令牌Token的认证策略
passport.use(new Strategy(
// 定义验证逻辑函数接收令牌token以及回调函数done作为参数
function (token, done) {
// 使用jsonwebtoken模块的verify方法验证传入的令牌token是否有效
// 传入令牌、配置中的密钥jwt_config.get("secretKey")以及验证回调函数验证回调函数接收验证结果err和解析后的令牌数据decode作为参数
jwt.verify(token, jwt_config.get("secretKey"), function (err, decode) {
// 如果验证过程中出现错误通过回调函数done返回错误信息给Passport表示令牌验证失败
if (err) { return done("验证错误"); }
// 如果验证成功通过回调函数done返回解析后的令牌数据decode给Passport表示令牌验证通过
return done(null, decode);
});
}
));
// 初始化passport模块
// 将Passport中间件初始化到应用程序app使其能够在后续的请求处理流程中生效用于处理各种认证相关的操作
app.use(passport.initialize());
// 如果传入了回调函数callback则执行该回调函数用于在初始化完成后执行额外的自定义操作
if (callback) callback();
};
/**
* 登录验证逻辑
* 此函数主要用于处理基于用户名和密码的登录请求验证逻辑通过调用Passport的认证中间件进行验证
* 根据验证结果生成相应的响应信息返回给客户端包括在验证成功时生成并返回JWT令牌等操作。
*
* @param {[type]} req 请求对象,包含了客户端发送的请求相关信息,如请求头、请求体等内容,常用于获取用户名、密码等登录信息。
* @param {[type]} res 响应对象,用于向客户端发送响应信息,如返回登录成功或失败的消息、生成的令牌等内容。
* @param {Function} next 传递事件函数用于将请求传递给下一个中间件继续处理在Express等框架的中间件链机制中使用此处未明确体现后续传递逻辑但遵循中间件规范保留该参数。
*/
module.exports.login = function (req, res, next) {
// 使用Passport的authenticate方法传入'local'表示采用之前配置的基于用户名和密码的本地认证策略进行认证,
// 同时传入一个回调函数用于处理认证结果该回调函数接收认证过程中的错误err、认证通过后的用户信息user以及额外的提示信息info作为参数
passport.authenticate('local', function (err, user, info) {
// 如果认证过程中出现错误使用响应对象res的sendResult方法这里假设是自定义的用于统一返回响应格式的方法向客户端发送包含错误状态码400表示请求错误和错误信息的响应
if (err) return res.sendResult(null, 400, err);
// 如果没有获取到用户信息即认证失败未找到匹配的用户同样使用响应对象的sendResult方法向客户端发送包含错误状态码和相应错误提示信息的响应
if (!user) return res.sendResult(null, 400, "参数错误");
// 获取角色信息
// 使用jsonwebtoken模块的sign方法生成JWT令牌传入包含用户IDuid和角色IDrid的对象、配置中的密钥以及令牌过期时间等配置信息生成一个有效的JWT令牌
var token = jwt.sign({"uid": user.id, "rid": user.rid}, jwt_config.get("secretKey"), {"expiresIn": jwt_config.get("expiresIn")});
// 将生成的令牌添加到用户对象中,并添加"Bearer "前缀符合Bearer Token的规范格式方便后续在请求头中传递和验证
user.token = "Bearer " + token;
// 使用响应对象的sendResult方法向客户端发送包含用户信息、成功状态码200以及登录成功消息的响应表示登录操作成功完成并返回相关用户数据和令牌
return res.sendResult(user, 200, '登录成功');
})(req, res, next);
};
/**
* token验证函数
* 此函数用于处理基于令牌Token的验证逻辑通过调用Passport的相应认证中间件验证传入的令牌是否有效
* 根据验证结果设置请求对象req中的用户信息并决定是否将请求传递给下一个中间件继续处理。
*
* @param {[type]} req 请求对象,包含了客户端发送的请求相关信息以及在验证通过后可用于存储用户相关数据等内容,方便后续中间件使用验证后的用户信息进行业务逻辑处理。
* @param {[type]} res 响应对象,用于向客户端发送响应信息,如在令牌验证失败时返回相应的错误消息等内容。
* @param {Function} next 传递事件函数,用于将请求传递给下一个中间件继续处理,在令牌验证通过后会调用该函数将请求传递下去,让后续中间件继续执行相应的业务逻辑。
*/
module.exports.tokenAuth = function (req, res, next) {
// 使用Passport的authenticate方法传入'bearer'表示采用之前配置的基于HTTP Bearer的认证策略进行令牌验证
// 同时传入{ session: false }表示不依赖会话Session进行验证常用于无状态的API认证场景如基于JWT的认证
// 并传入一个回调函数用于处理验证结果该回调函数接收验证过程中的错误err以及验证通过后的令牌数据tokenData作为参数
passport.authenticate('bearer', { session: false }, function (err, tokenData) {
// 如果验证过程中出现错误使用响应对象res的sendResult方法向客户端发送包含错误状态码400表示请求错误和相应错误提示信息无效token的响应
if (err) return res.sendResult(null, 400, '无效token');
// 如果没有获取到有效的令牌数据即令牌验证失败同样使用响应对象的sendResult方法向客户端发送包含错误状态码和相应错误提示信息的响应
if (!tokenData) return res.sendResult(null, 400, '无效token');
// 如果令牌验证通过在请求对象req中创建一个空的用户信息对象userInfo用于存储从令牌中解析出的相关用户信息方便后续中间件使用
req.userInfo = {};
// 将从令牌数据tokenData中解析出的用户IDuid存储到请求对象的用户信息对象中
req.userInfo.uid = tokenData["uid"];
// 将从令牌数据tokenData中解析出的角色IDrid存储到请求对象的用户信息对象中
req.userInfo.rid = tokenData["rid"];
// 调用传递事件函数next将请求传递给下一个中间件继续处理表示令牌验证通过后续中间件可以基于请求对象中的用户信息进行相应的业务逻辑操作
next();
})(req, res, next);
}