Предотвратить Expressjs от создания сеанса, когда запросы содержат заголовок авторизации?
У меня есть API, который можно вызвать либо с помощью браузера, где запросы являются транзакционными и имеют сеанс ИЛИ напрямую, например. используя curl, где запросы являются атомарными. Запросы браузера должны сначала пройти аутентификацию, а затем использовать экспресс-сеанс (connect.sid) для последующей авторизации, прямые вызовы API используют заголовок:Authorization: "SOMETOKEN"
который должен быть отправлен для каждого запроса.
У меня проблема в том, что, поскольку я использую один и тот же веб-сервер для обслуживания как атомарного, так и транзакционного трафика, каждый вызов API без необходимости получает сеанс Express. Каждый ответ включает в себя Set-Cookie, и все эти сеансы заполняют мое хранилище сеансов. Следовательно:Как я могу запретить Express вводить новый ключ sess в хранилище памяти (Redis), если запрос содержит заголовок авторизации?
Запись. Я понимаю, что более классический подход состоит в том, чтобы иметь отдельный API-сервер и отдельный WEB-сервер, но почему бы не запустить оба на одной машине? Для меня разница в том, что API обслуживает данные, а WEB обслуживает представления, но помимо этого они оба являются частью одного и того же приложения. Я просто позволяю пользователям напрямую получать доступ к своим данным и не заставляю их использовать мой интерфейс.
Экспресс Конфигmodule.exports = function(app, exp, sessionStore, cookieParser, passport, flash) {
app.configure(function(){
// Templates
app.set('views', ERNEST.root + '/server/views');
app.set('view engine', 'jade');
app.set('view options', { doctype : 'html', pretty : true });
// Allow large files to be uploaded (default limit is 100mb)
app.use(exp.limit('1000mb'));
// Faux putting and deleting
app.use(exp.methodOverride());
// Static content
app.use(exp.static(ERNEST.root + '/server'));
app.use(exp.static(ERNEST.root + '/public'));
// Handle favicon
app.use(exp.favicon());
// For uploads
app.use(exp.bodyParser({keepExtensions: true}));
// Configure cookie parsing
if ( cookieParser ) app.use(cookieParser);
else app.use(exp.cookieParser());
// Where to store the session
var session_options = { 'secret': "and she put them on the mantlepiece" };
if ( sessionStore ) session_options.store = sessionStore;
app.use(exp.session( session_options ));
// Rememberance
app.use( function (req, res, next) {
if ( req.method == 'POST' && req.url == '/authenticate' ) {
if ( req.body.rememberme === 'on' ) {
req.session.cookie.maxAge = 2592000000; // 30*24*60*60*1000 Rememeber 'me' for 30 days
} else {
req.session.cookie.expires = false;
}
}
next();
});
// PassportJS
if ( passport ){
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
}
});
};
Пример маршрутаapp.get('/status/past_week', MID.ensureAuthenticated, MID.markStart, function(req, res) {
WEB.getStatus('week', function(err, statuses){
if ( err ) res.send(500, err);
else res.send(200, statuses);
});
});
Средство авторизацииMID.ensureAuthenticated = function(req, res, next) {
if ( req.isAuthenticated() ) return next();
else {
isAuthorised(req, function(err, authorised){
if ( err ) return res.redirect('/');
else if ( authorised ) return next();
else return res.redirect('/');
});
}
function isAuthorised(req, callback){
var authHeader = req.headers.authorization;
if ( authHeader ) {
// Has header, verify it
var unencoded = new Buffer(authHeader, 'base64').toString();
var formatted = unencoded.toString().trim();
ACCOUNT.verifyAuth(formatted, callback); // verifyAuth callbacks next() when successful
} else callback(null, false); // No Authorised header
}
};