passport-local-mongoose:createStrategy 不是一个函数/authenticate 不是一个函数
Posted
技术标签:
【中文标题】passport-local-mongoose:createStrategy 不是一个函数/authenticate 不是一个函数【英文标题】:passport-local-mongoose: createStrategy is not a function / authenticate is not a function 【发布时间】:2017-11-26 21:17:18 【问题描述】:我在this starter project 之上构建并尝试使用passport-local-mongoose 添加用户登录。
根据我尝试使用该策略的两种方式中的哪一种,我会收到以下错误:
[1] passport.use(User.createStrategy());
[1] ^
[1] TypeError: User.createStrategy is not a function
或者这个错误:
[1] passport.use(new LocalStrategy(User.authenticate()));
[1] ^
[1] TypeError: User.authenticate is not a function
我已经尝试在谷歌上搜索很多解决方案,但似乎找不到任何相关内容。
编辑:据我了解,./models/user.ts
中的userSchema.plugin(passportLocalMongoose);
应该将功能添加到模型中。 Configure Passport/Passport-Local 和 Simplified Passport/Passport-Local Configuration 展示了如何设置它,但它似乎对我不起作用。
相关依赖版本:
"dependencies":
"cookie-parser": "^1.4.3",
"express": "^4.14.0",
"express-session": "^1.15.3",
"mongoose": "^4.7.2",
"passport": "^0.3.2",
"passport-local": "^1.0.0",
"passport-local-mongoose": "^4.0.0",
"session-file-store": "^1.0.0",
"typescript": "~2.2.0",
,
"devDependencies":
"ts-node": "~2.0.0",
,
./models/user.ts
import * as mongoose from 'mongoose';
const passportLocalMongoose = require('passport-local-mongoose');
const userSchema = new mongoose.Schema(
email: String,
password: String,
displayname: String,
groups: [
type: mongoose.Schema.Types.ObjectId,
ref: 'Group'
]
);
userSchema.plugin(passportLocalMongoose,
usernameField: 'email'
);
const User = mongoose.model('User', userSchema);
export default User;
./app.ts 的相关部分
import * as express from 'express';
import * as cookieParser from 'cookie-parser';
import * as session from 'express-session';
const FileStore = require('session-file-store')(session);
import * as mongoose from 'mongoose';
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const app: express.Express = express();
const cookieSecret = 'asdf';
app.use(cookieParser(cookieSecret));
app.use(session(
secret: cookieSecret,
resave: false,
saveUninitialized: false,
store: new FileStore()
));
// Configure passport middleware
app.use(passport.initialize());
app.use(passport.session());
// Configure passport-local to use User model for authentication
const User = require('./models/user');
passport.use(User.createStrategy());
// Alternatively: passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
完成./app.ts
import * as express from 'express';
import * as bodyParser from 'body-parser';
import * as cookieParser from 'cookie-parser';
import * as session from 'express-session';
const FileStore = require('session-file-store')(session);
import * as path from 'path';
import * as logger from 'morgan';
import * as mongoose from 'mongoose';
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
// import index from './routes/index';
// import users from './routes/users';
const app: express.Express = express();
// // view engine setup
// app.set('views', path.join(__dirname, 'views'));
// app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
// app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded( extended: false ));
const cookieSecret = '';
app.use(cookieParser(cookieSecret));
app.use(session(
secret: cookieSecret,
resave: false,
saveUninitialized: false,
store: new FileStore()
));
app.use(express.static(path.join(__dirname, 'public')));
// Configure passport middleware
app.use(passport.initialize());
app.use(passport.session());
// Configure passport-local to use User model for authentication
const User = require('./models/user');
passport.use(User.createStrategy());
// Alternatively: passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// app.use('/', index);
// app.use('/users', users);
// routes
const routeModules = require('require-all')(
dirname: __dirname + '/routes',
filter: (filename: string) =>
filename = filename.toLowerCase();
if ((filename.endsWith('.ts') && !filename.endsWith('.spec.ts'))
|| (filename.endsWith('.js') && !filename.endsWith('.spec.js')))
return filename.substr(0, filename.length - 3);
,
map: name => '/' + name
);
function resolve(root: string, modules): void
for (const name of Object.keys(modules))
if (!name.startsWith('/'))
return;
const module = modules[name];
if (module.default && module.default.route)
console.log(`Add router $root + name`);
const router = module.default as express.Router;
app.use(root, router);
else
resolve(root + name, module);
resolve('', routeModules);
// Default to main page, angular route takes over
app.use((req, res) =>
res.sendFile(path.join(__dirname, 'public/index.html'));
);
// // catch 404 and forward to error handler
// app.use((req, res, next) =>
// var err = new Error('Not Found');
// err['status'] = 404;
// next(err);
// );
// // error handlers
// // development error handler
// // will print stacktrace
// if (app.get('env') === 'development')
// app.use((error: any, req, res, next) =>
// res.status(error['status'] || 500);
// res.render('error',
// message: error.message,
// error
// );
// );
//
// // production error handler
// // no stacktraces leaked to user
// app.use((error: any, req, res, next) =>
// res.status(error['status'] || 500);
// res.render('error',
// message: error.message,
// error:
// );
// return null;
// );
export default app;
// Connect to MongoDB
mongoose.connect('mongodb://localhost/test');
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () =>
console.log('MongoDB connected');
);
【问题讨论】:
您在 User 对象中没有任何功能,我认为如果您使用 passport.authenticate 它会起作用 @ArpitSolanki 据我了解 userSchema.plugin(passportLocalMongoose);应该添加功能。 github.com/saintedlama/passport-local-mongoose 上的“配置 Passport/Passport-Local”和“简化的 Passport/Passport-Local 配置”记录了如何设置它,但它似乎对我不起作用。 【参考方案1】:像这样更新你的 user.ts 文件:
import * as mongoose from 'mongoose';
import * as passportLocalMongoose from 'passport-local-mongoose';
import PassportLocalSchema from 'mongoose';
const userSchema = new mongoose.Schema(
email: String,
password: String,
displayname: String,
groups: [
type: mongoose.Schema.Types.ObjectId,
ref: 'Group'
]
);
userSchema.plugin(passportLocalMongoose,
usernameField: 'email'
);
const User = mongoose.model('User', userSchema as PassportLocalSchema);
export default User;
它对我有用。
【讨论】:
对我不起作用 :( 但是当我读到这个答案时,我感到希望 :)))【参考方案2】:抱歉回复晚了。我找到了解决这个问题的方法。
import mongoose, PassportLocalSchema from 'mongoose';
import passportLocalMongoose from 'passport-local-mongoose';
const Schema = mongoose;
const UserSchema = new Schema();
UserSchema.plugin(passportLocalMongoose);
const User: mongoose.PassportLocalModel<mongoose.PassportLocalDocument> =
mongoose.model('User', UserSchema as PassportLocalSchema );
export default User;
【讨论】:
【参考方案3】:如果我理解正确的话,这只是一个未解析的类型引起的,并不是真正的代码错误。
解决它 -
在您的项目中包含类型定义文件,这将扩展 mongoose 中的类型:https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/passport-local-mongoose/index.d.ts
在您的app.ts
中,从mongoose
导入所需的类型(注意PassportLocalModel
来自上面的定义文件):
import Document, PassportLocalModel from "mongoose";
-
现在您可以将更新后的类型转换为
User
:
(User as PassportLocalModel<Document>).createStrategy()
(User as PassportLocalModel<Document>).authenticate()
【讨论】:
【参考方案4】:为了解决这个问题,我检查了他们如何实际测试类型 - https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/passport-local-mongoose/passport-local-mongoose-tests.ts 用法变得非常清楚。
以下对我有用(请注意 PassportLocalDocument、PassportLocalSchema、PassportLocalModel 的用法):
import mongoose,
PassportLocalDocument,
PassportLocalSchema,
PassportLocalModel,
from 'mongoose';
import passportLocalMongoose from 'passport-local-mongoose';
import updateIfCurrentPlugin from 'mongoose-update-if-current';
export enum UserStatus
Created = 'created',
Approved = 'approved',
Banned = 'banned',
export enum UserRole
Member = 'member',
Admin = 'admin',
Public = 'public',
// An interface for props to create a new user
interface UserAttrs
email: string;
password: string;
status?: UserStatus;
role?: UserRole;
// An interface that describes the properties of User document
interface UserDoc extends PassportLocalDocument
email: string;
password: string;
status: UserStatus;
role: UserRole;
// An interface that describes User model
export interface UserModel extends PassportLocalModel<UserDoc>
build(attrs: UserAttrs): UserDoc;
const userSchema = new mongoose.Schema(
email:
type: String,
required: true,
,
password:
type: String,
required: true,
,
status:
type: String,
required: true,
,
role:
type: String,
required: true,
,
,
toJSON:
transform(doc, ret)
delete ret.password;
ret.id = ret._id;
delete ret._id;
,
,
,
) as PassportLocalSchema;
userSchema.set('versionKey', 'version');
userSchema.plugin(passportLocalMongoose,
usernameField: 'email',
);
userSchema.plugin(updateIfCurrentPlugin);
userSchema.statics.build = (attrs: UserAttrs) =>
return new User(attrs);
;
const User = mongoose.model<UserDoc, UserModel>('User', userSchema);
export User ;
【讨论】:
【参考方案5】:我遇到了同样的问题,我通过添加解决了它:
userSchema.plugin(passportLocalMongoose);
这段代码在 userSchema声明在用户模式模型声明之前。
示例:
mongoose.connect("mongodb://localhost:27017/userDB",
useNewUrlParser: true,
useUnifiedTopology: true
);
// userSchema
const userSchema = new mongoose.Schema(
email: String,
password: String
);
//**Like this**
userSchema.plugin(passportLocalMongoose);
// User Schema model
const User = new mongoose.model("User", userSchema);
mongoose.set("useCreateIndex", true);
【讨论】:
这对我有用:)【参考方案6】:它对我有用。尝试使用这种格式:
userSchema.plugin(passportLocalMongoose);
const User = mongoose.model("User",userSchema);
【讨论】:
以上是关于passport-local-mongoose:createStrategy 不是一个函数/authenticate 不是一个函数的主要内容,如果未能解决你的问题,请参考以下文章
找到一种使用 passport-local-mongoose 更新用户护照的方法