使用koa和护照进行身份验证

mfc*_*mfc 4 authentication routing koa passport.js

我正在使用koa和passport尝试实现中间件,以防止在未经过身份验证时访问URI.

var koa = require('koa');
var session = require('koa-generic-session');
var bodyParser = require('koa-bodyparser');
var koaRouter = require('koa-router');
var passport = require('koa-passport');
var views = require('co-views');
var render = views('.', { map: { html: 'swig' }});
var localStrategy = require('passport-local').Strategy;

var app = koa();
var router = koaRouter();

app.keys = ['secret'];
app.use(session());
app.use(bodyParser());
app.use(passport.initialize());
app.use(passport.session());

passport.serializeUser(function(user, done) {
    done(null, user);
});

passport.deserializeUser(function(user, done) {
    done(null, user);
});

passport.use(new localStrategy(function(username, password, done) {
    if (username === 'user1' && password === 'password2') {
        done(null, { userId: 99, userName: 'redBallons' });
    } else {
        done(null, false);
    }
}));

router.get('/login', function *(next) {
    this.body = yield render('index.html');
});

router.post('/login', passport.authenticate('local', {
    successRedirect: '/secretBankAccount',
    failureRedirect: '/login'
}));

router.get('*', function *(next) {
    if (! this.isAuthenticated()) {
        console.log('not authenticated');
        this.redirect('/login');
    } else {
        console.log('authenticated');
        yield next;
    }
});

router.get('/secretBankAccount', function *(next) {
    this.body = '2 dollars';
});

app.use(router.routes());
app.listen(8080);
Run Code Online (Sandbox Code Playgroud)

但是,我永远无法访问我的秘密银行帐户.我可以输入正确的用户名和密码,并且可以看到已验证的消息,但router.get('*')中的下一个产量不会传递给下一个路由功能

Pea*_*yle 5

在使用时koa-router,预计只有一条路线被击中.所以当你到达'*'路线时,即使你也不会打到另一条路线yield next.

因此,您应该使用自己的身份验证中间件替换通用路由:

app.use(function*(next) {
  if (this.isAuthenticated()) {
    yield next
  } else {
    this.redirect('/login')
  }
});
Run Code Online (Sandbox Code Playgroud)

身份验证中间件将强制您使用两个路由对象而不是一个路由对象进行路由.这样您就可以区分公共路线和安全路线.所以类似于:

var public = new koaRouter();

public.get('/login', function *(next) {
    this.body = yield render('index.html');
});

public.post('/login', passport.authenticate('local', {
    successRedirect: '/secretBankAccount',
    failureRedirect: '/login'
}));

app.use(public.routes());

app.use(function*(next) {
  if (this.isAuthenticated()) {
    yield next;
  } else {
    this.redirect('/login');
  }
})

var secured = new koaRouter();

secured.get('/secretBankAccount', function *(next) {
  this.body = '2 dollars';
});

app.use(secured.routes());
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,请求将首先命中公共路由中间件.然后,如果它与当前请求与公共路由不匹配,它将转移到认证中间件.如果isAuthenticated()false重定向将发生.如果isAuthenticated()true,它会移动到安全的路由.

这种方法基于koa-passport-example项目,该项目由作者创建koa-passport.