DWi*_*ick 5 typescript google-oauth passport.js nestjs
我有一个 NestJS 应用程序,其中包含一些身份验证逻辑。登录是使用 Passport 为 Google Oauth 实现的,似乎可以正常工作,但在服务器上我会出现此错误:
(node:19195) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Run Code Online (Sandbox Code Playgroud)
我谷歌了一下,似乎常见的原因之一可能是向客户端发送几次响应。话虽如此,我无法在我的代码中发现这一点,所以我怀疑这是否是原因。以下是相关的片段。
使用@nestjs/passport 对用户进行序列化和反序列化。
@Injectable()
export class GoogleSerializer extends PassportSerializer {
constructor(private readonly usersService: UsersService) {
super();
}
public serializeUser(user: User, done: Function) {
console.log('serialize', user);
if (user) {
done(null, user.id);
} else {
done(null);
}
}
public async deserializeUser(id: number, done: Function) {
console.log('deserialize', id);
this.usersService.findById(id).then(user => {
done(null, user);
}).catch(error => {
done(error, null);
});
}
}
Run Code Online (Sandbox Code Playgroud)
这是 Passport JS 的 Google 策略:
@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy) {
constructor(private readonly usersService: UsersService) {
super({
clientID:
'client',
clientSecret: 'I'm-secret',
callbackURL: '/auth/google/callback',
scope: ['email', 'profile'],
});
}
async validate(accessToken, refreshToken, profile, done) {
const user = <create the user object from google profile>
this.usersService.findOne(user.email).then(userEntity => {
if (!userEntity) {
this.usersService.createOne(user);
}
});
return this.usersService
.findOne(user.email)
.then(user => {
done(null, user);
return user;
})
.catch(error => {
done(error);
return null;
});
}
}
Run Code Online (Sandbox Code Playgroud)
这是 AuthController 的路由:
@Controller('auth')
export class AuthController {
@Get('/google/callback')
async googleCallback(@Req() req, @Res() res, @Next() next) {
passport.authenticate('google', {
successReturnToOrRedirect: '/users/test',
failureRedirect: '/auth/login'
})(req, res, next);
}
@Get('/login')
async login(@Req() req) {
return '<a href="/auth/google/login">Login</a>';
}
@Get('/google/login')
async googleLogin(@Req() req, @Res() res, @Next() next) {
passport.authenticate('google', { scope: ['profile', 'email'] })(req, res, next);
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个用户需要登录的路径的中间件:
@Injectable()
export class LoginRequired implements NestMiddleware {
resolve(...args: any[]): MiddlewareFunction {
console.log('calling loginrequired');
return (req, res, next) => {
if (!req.isAuthenticated || !req.isAuthenticated()) {
if (req.session) {
req.session.returnTo = req.originalUrl || req.url;
}
return res.redirect('/auth/login');
}
next();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是设置阶段:
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: true,
cookie: { secure: false }}));
app.use(passport.initialize());
app.use(passport.session());
Run Code Online (Sandbox Code Playgroud)
例如,我尝试转到受此中间件保护的 /user 并且应该将用户发送到登录页面,该页面提示用户登录并将用户带到 /user 页面。一切正常,但我得到了
发送到客户端后无法设置标头
任何想法是如何发生的?
我使用 Pasport js 和 NestJs。
| 归档时间: |
|
| 查看次数: |
424 次 |
| 最近记录: |