egg-passport-local,how to set response body?

Created on 6 May 2018  ·  19Comments  ·  Source: eggjs/egg

Egg,我是用来做RESTful,api服务器,所以返回成功或失败跳转,意义不大

 app.passport.verify(async (ctx, user) => {
    ctx.logger.debug('passport.verify', user)

    // 我试过下面的方案,不行
    if (true) {
      ctx.body = { status: 'success' }
    } else {
      ctx.body = { status: 'error' }
    }

    // 下面这样的写法,也不行
    const err = new Error('错误了');
    err.code = 'error_code';
    throw err

    // return existUser
    return user
  })

我是配合 ant design pro用的。登录成功后,跳转页面,也是由ant design pro判断status来处理的。如果status === 'error',我会返回额外信息,由ant design pro页面提示错误,比如密码不正确

All 19 comments

i have same problem。

还有一个疑问,这个验证,无论成功或者失败,都是返回302。我可以手工指定返回码吗,比如返回200?

// 鉴权
const localStrategy = app.passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/api/signIn'
});

跳到相应的(api)页面应该可以处理,verify里面只是校验。这种方式虽然可以。但是好像开发思路有点不直观。

对,除了不直观,而且,缺乏有效返回错误信息的途径。只是用来写RESTful,api服务器,前端是react

我设计的流程是,如果验证失败,return null,body={ status: 'error', type: 'password' }。
我前端接收到返回的body,就可以渲染页面,提示密码错误,不需要跳转

http://www.passportjs.org/docs/login/ 可以看看这个,看看有没有解决方案了。

好的,我看看去

@fengmk2 @popomore 大神,求助哈

这里的问题好像在群里讨论过

  • verify 处理用户数据,返回 user / null / errorObject 等(不建议在这里抛出异常)
  • deserializeUser 获取用户数据,可以在这一步处理用户信息或者错误提示等

参考:

谢谢,egg-cnode这个我之前看过了。

刚粗略看了下passport和passport-local的源码,想实现我设想的功能,需要改源码,默认是实现不了的。

改源码简单,维护起来就麻烦了,每次重置库,都需要再次修改库代码

仔细看了下源码,如果直接用passport和passport-local,可以通过callback来实现。但是,egg-passport不支持传递callback

authenticate函数忽略了第四个参数callback,下面代码摘自egg-passport/lib/framework.js

function authenticate(passport, name, options) {
  // Don't support authenticate with callback

  // function authenticate(req, res, next)
  const connectMiddleware = connectFramework.authenticate(passport, name, options);

  debug('use authenticate:%s, options: %j', name, options);

@fengmk2 @popomore 大神给点建议哈

其实如果只是账号登陆的话,都没必要用 passport-local,自己做一个 post 就完事了。

Passport 是设计来给第三方登陆用的。

我在[email protected]@passport\lib\middlewaremd5-8e9fd8402a16b5ddb359a7847a3e15b9uthenticate.js手工硬加入下面代码,就可以了。先凑合着用,后面再想办法,第三方登录是需要的,想统一登录,所以想用passport

  return function authenticate(req, res, next) {
    if (http.IncomingMessage.prototype.logIn
        && http.IncomingMessage.prototype.logIn !== IncomingMessageExt.logIn) {
      require('../framework/connect').__monkeypatchNode();
    }


>     callback = function(err, user, info) {
>       if (err) { return next(err) }
> 
>       if (user.error) {
>         return res.end(user.body)
>       }
> 
>       req.logIn(user, function(err) {
>         if (err) { return next(err) }
>         return res.end(user.body)
>       })
>     }

    // accumulator for failures from each strategy in the chain
    var failures = [];

node_modules 一般不要动,npm update 一下就没了。

没啥必要统一

明白了,那我不用了,还是直接单独写个post吧,谢谢

其实可以给 app.passport.authenticate 包成一个 promise,通过中间件的方式在 route 中使用,就可以直接返回 json 了。

// middleware/auth.js

'use strict';

module.exports = () => {
  return async function(ctx, next) {
    const app = ctx.app;
    if (app.passport) {
      const localStrategy = new Promise(resolve => {
        app.passport.authenticate('local', (err, user) => {
          if (err) {
            resolve({ success: false, message: err });
          }

          if (!user) {
            resolve({ success: false, message: 'current user not exit.' });
          }

          resolve(user);
        })(ctx);
      });

      ctx.body = await localStrategy.then(res => res);
      await next();
    }
  };
};

@atian25 我觉得对于passport来说,这个密码登录的功能可能没特别的必要。不过保持koa插件功能完整还是很有必要的。不过我看以现在egg把插件功能打散这种方式,可能有些功能实现起来有些麻烦。

@whlsxl 就这个问题来说,我个人觉得是 passport 的问题,毕竟它是 express 风格的插件,来转换为 koa 风格,毕竟 hacky 。 打散这个也不是 egg 本意,而是 Passport 本身就分为那么多 Strategy

我的做法是 自己判断登录 然后
ctx.login(user); 传给passport(用于利用 sessiong 和 登录验证方法ctx.isAuthenticated)
`
async login() {
if(true){
ctx.login(user)
}
}

async currentUser() {
const { ctx } = this;
if (ctx.isAuthenticated()) {
ctx.body= {username:'aaa'};
}else{
ctx.response.status = 401;
}
}

`

Was this page helpful?
0 / 5 - 0 ratings