node.js - Passport RESTAPI 身份验证

标签 node.js rest authentication grouping passport.js

我是 Node Passport 身份验证的新手。我完整的写了一个 Passport 认证的例子如下:

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 分组到一个策略中?

最佳答案

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

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/下的所有请求启用 Passport 中间件,以便用户需要使用 Passport 本地策略进行身份验证。然后可以在不包含 Passport 中间件的情况下实现/api/data/下各个端点的逻辑。

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

关于node.js - Passport RESTAPI 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34629340/

相关文章:

node.js - 模板网址不起作用

ruby-on-rails - 在事件资源请求中设置 header

java - 如何从我的 Android 设备访问本地 REST API?

javascript - Puppeteer - 单击具有指定文本的跨度

javascript - 使用 Express 发送和接收数据

rest - Office 365 事件日志 API

ruby-on-rails - 从 Rails 到 Phoenix 共享身份验证/数据?

python - GAE中如何处理不同类别的用户?

php - 生成用于 Web 服务身份验证的访问 token 的函数

node.js - Firebase Auth 使用 NodeJS 验证 JWT ID token ,无需 SDK