护照RESTAPI身份验证

时间:2016-01-06 09:13:27

标签: node.js rest authentication grouping passport.js

我是Node护照认证的新手。我完整地写了一个护照认证的例子如下:

var express = require('express');

var passport = require('passport');
var passportLocal = require('passport-local');

/* 
Since express doesn't support sessions by 
default you need following middlewares.
*/
// For storing session ID in browser
var cookieParser = require('cookie-parser');

// For rendering credentials from request bodies
var bodyParser = require('body-parser');

/*
For server side storage of session information.
All these session information is in server memory. 
If the machine app reboot all sessions infromation 
will disapear. The information coming with request
, thanks to cookies, with the session information
stored in the server used in deserializing the users.
Be careful properly handle session information
in server farms, round robbining and load balancing etc.
But it is easy to configure express-session middleware
to use external storage. In this case we use local machine.
*/
var expressSession = require('express-session');

var app = express();

app.set('view engine', 'ejs');

// For sessions. Need before Passport middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(expressSession({
    // This is the secret used to sign the session ID cookie.
    secret: process.env.SESSION_SECRET || 'd7n5ihsxx9by8ydt',
    resave: false,
    saveUninitialized: false
}));

// Passport need 2 middlewares
app.use(passport.initialize());
app.use(passport.session());

/*
Strategies need to be told how to veryfy username and password
that is inside authorization header that is client is goint to send.
*/
function verifyCredentials(username, password, done) {
    /*
    Use crypto.pbkdf2(password, salt, iterations, keylen[, digest], callback)
    For the real app.
    */
    if (username === password) {
        /*
        done() first argument is Error
        Second argument 'user' is any object required for your business logic.
        But make it as much as smaller for fast serializing and deserializing.
        */
        done(null, {
            id : 123,
            name: username,
            role: 'Admin',
            catogery : 'Operator'
        });
    } else {
        done(null, null);
    }
};

/*
Now we have to configure passport. Call the local strategy with
single function function(username, password, done) where done is callback
funciton.
*/
passport.use(new passportLocal.Strategy(verifyCredentials));

/*
passport.serializeUser serializes the 'user' object.
The callback function done, need a small piece of
'user' object which is required in deserializing.
In following case 'user.id' is saved to session 
req.session.passport.user = {id:'..'}
*/
passport.serializeUser(function(user, done) {
    done(null, user.id);
});

/*
In deserialize function you provide in first argument of 
deserialize function that same key of user object that was 
given to done function in serialize call. So your whole object is
retrieved with help of that key. that key here is id. 
In deSerialize function that key is matched with in 
memory array / database or any data resource.
*/
passport.deserializeUser(function(id, done){
    /*
    Query database or cache here! Example

    User.findById(id, function(err, user) {
        done(err, user);
    });
    */
    done(null, {
        id : id,
        name: id,
        role: 'Admin',
        catogery : 'Operator'
    }); 
});

/*
Middleware for API's. 3rd party middlewares are available
to download and install if you want. Middleware is 
nothing but a simple function with the following format.
'next' is callback function which is used to pass the request
to the next middleware inline.
*/
function ensureAuthenticated(req, res, next){
    if(req.isAuthenticated()){
        next();
    } else {
        res.status(403).json( {msg: '403 Forbidden'} ); 
    }
}

app.get('/', function(req, res) {
    res.render('index', {
        /*
        Express doesn't have isAuthenticated for req. 
        But passport add it to req. Also the 'user' object
        added in done() callback is available through req.
        */
        isAuthenticated : req.isAuthenticated(),
        user : req.user
    });
});

app.get('/login', function(req, res) {
    res.render('login');
});

app.get('/logout', function(req, res) {
    //Passport add logout method to request object
    req.logout();
    res.redirect('/');
});

/*
In this end point, the middleware passport.authenticate('local') is called.
passport.authenticate('local') returns a functon similar to ensureAuthenticated.
*/
app.post('/login', passport.authenticate('local'), function(req, res) {
    res.redirect('/');
});

/*
Second endpoint for API's. The endpoint is authenticated
with a middleware which is between URI and function.
*/
app.get('/api/data', passport.authenticate('local'), function(req, res) {
    res.json([
        {name: 'My'},
        {name: 'Kumara'}
    ]);
});

app.get('/api/data/me', function(req, res) {
    res.json([
        {name: 'My'},
        {name: 'Kumara'}
    ]);
});

var port = process.env.PORT || 3000;

app.listen(port, function() {
    console.log('Server is running on Port : ' + port);
})

我的问题: 我有两个URI:

/api/data
/api/data/me

我认为自从我对/api/data进行了身份验证后,它会自动验证/api/data/me,因为/api/data部分已经过身份验证,/api/data/me就像/api/data的孩子一样。但事实并非如此。这是否意味着我必须对每个API进行身份验证?

如果没有,我如何在一个策略中对一组API进行分组?

1 个答案:

答案 0 :(得分:0)

通配符可用于匹配特定路径下的所有内容。例如:

app.get('/api/data/*', passport.authenticate('local'), function(req, res, next) {
    next(); // call next matching route
});

app.get('/api/data/me', function(req, res) {
    res.json([
       {name: 'My'},
       {name: 'Kumara'}
    ]);
});

这为/ api / data /下的所有请求启用了护照中间件,以便用户需要使用护照本地策略进行身份验证。然后可以在不包括护照中间件的情况下实现/ api / data /下各个端点的逻辑。

有关用户指南中的快速路线匹配的更多信息。 http://expressjs.com/en/guide/routing.html