Passport
身份验证是大多数 Web 应用程序的重要组成部分。因此 Midway 封装了目前 Node.js 中最流行的 Passport 库。
Passport 是通过称为策略的可扩展插件进行身份验证请求。Passport 不挂载路由或假设任何特定的数据库,这最大限度地提高了灵活性并允许开发人员做出应用程序级别的决策。
准备
- 安装
npm i @midwayjs/passport
$ npm i @midwayjs/passport@2 passport --save
$ npm i @types/passport --save-dev
- 如果你需要保存到 session 中,开启相对应框架的 session 功能
使用
这里我们以本地认证,和 JWT 作为演示,这里用到了另一个 JWT 组件。
首先
// src/configuration.ts
import { ILifeCycle } from '@midwayjs/core';
import { Configuration } from '@midwayjs/decorator';
import * as jwt from '@midwayjs/jwt';
import * as passport from '@midwayjs/passport';
@Configuration({
imports: [jwt, passport],
// ...
})
export class ContainerLifeCycle implements ILifeCycle {}
e.g. 本地策略
我们可以通过 @CustomStrategy
和派 生 PassportStrategy
来 自启动一个策略。通过 validate 钩子来获取有效负载,并且此函数必须有返回值,其参数并不明确,可以参考对应的 Strategy 或者通过展开符打印查看。
// strategy/local.ts
import { CustomStrategy, PassportStrategy } from '@midwayjs/passport';
import * as bcrypt from 'bcrypt';
@CustomStrategy()
export class LocalStrategy extends PassportStrategy(Strategy) {
async validate(user, password) {
// 实际的秘钥
const password = '*********';
// 和用户的秘钥做对比
const isLegalUser = await bcrypt.compare(password, user.password);
if (!isLegalUser) {
throw new Error('error password ' + user.name);
}
return {
user,
password,
};
}
// 当前策略的参数
getStrategyOptions(): any {
return {
passwordField: 'pwd',
};
}
}
之后派生PassportMiddleware
出一个中间件。
// local-middleware.ts
import { Inject, Provide } from '@midwayjs/decorator';
import { PassportMiddleware } from '@midwayjs/passport';
import { Context } from '@midwayjs/express';
@Provide('local') // 此处可以使用一个简短的identifier
export class LocalPassportMiddleware extends PassportMiddleware(LocalStrategy) {
// 设置 AuthenticateOptions
getAuthenticateOptions(): Promise<passport.AuthenticateOptions> | passport.AuthenticateOptions {
return {
failureRedirect: '/login',
presetProperty: 'user',
};
}
}
// controller.ts
import { Provide, Post, Inject, Controller } from '@midwayjs/decorator';
@Provide()
@Controller('/')
export class LocalController {
@Post('/passport/local', { middleware: ['local'] })
async localPassport() {
console.log('local user: ', this.ctx.req.user);
return this.ctx.req.user;
}
}