节点js跨域验证

Arp*_*mar 8 javascript authentication node.js express mean-stack

我正在研究MEAN应用程序,我正在为我的项目使用Angular 4.对于身份验证,我已经实现了Passport js Local-strategy.我正在维护持久会话Express-session.事情一直很好,直到这里.

问题

在同一个域session工作正常,我能够验证用户.但在跨域,我无法维持会话.它为跨域中的每个新请求生成新的会话ID.

然后我尝试Passport-jwt但问题是我没有对用户会话的控制.我的意思是如果用户不活动,甚至在服务器重新启动时也token无法从服务器注销用户也不会失效.

所以简单来说,我正在寻找Node js(Express js)中的身份验证解决方案,我可以在其中管理跨域身份验证.

我已经看到了一些博客文章和像这样的问题这样,但它并不能帮助.

谢谢.

编辑

我应该编写自己的代码来实现这一目标吗?如果是这样,我有一个计划.

我的基本计划是:

  1. 用户将使用登录请求发送凭据.
  2. 我将检查数据库中的凭据.如果凭证有效,我将生成一个随机令牌并将其保存到用户表中的数据库中,并且我将通过成功响应向用户提供相同的令牌.
  3. 现在,每个请求用户都将发送令牌,我将检查数据库中每个请求的令牌.如果令牌有效,那么我将允许用户访问API,否则我将生成401状态代码的错误.
  4. 我正在使用Mongoose(MongoDB),所以我可以检查每个请求中的令牌(性能观点).

我认为这也是一个好主意.我只是想要一些建议,无论我是否正在考虑正确的方向.

我会得到这个:

  1. 应用程序中登录用户的数量(活动会话).
  2. 如果用户空闲一段时间,我可以注销用户.
  3. 我可以管理同一用户的多个登录会话(通过在数据库中进行输入).
  4. 我可以允许最终用户清除所有其他登录会话(如Facebook和Gmail优惠).
  5. 任何与授权相关的定制.

编辑2

我在这里分享我的app.js代码

var express = require('express');
var helmet = require('helmet');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var dotenv = require('dotenv');
var env = dotenv.load();
var mongoose = require('mongoose');
var passport = require('passport');
var flash    = require('connect-flash');
var session      = require('express-session');
var cors = require('cors');

var databaseUrl = require('./config/database.js')[process.env.NODE_ENV || 'development'];
// configuration 
mongoose.connect(databaseUrl); // connect to our database

var app = express();

// app.use(helmet());

// required for passport


app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
  if ('OPTIONS' == req.method) {
       res.send(200);
   } else {
       next();
   }
});


app.use(cookieParser());

app.use(session({
    secret: 'ilovescotchscotchyscotchscotch', // session secret
    resave: true,
    saveUninitialized: true,
    name: 'Session-Id',
    cookie: {
      secure: false,
      httpOnly: false
    }
}));


require('./config/passport')(passport); // pass passport for configuration

var index = require('./routes/index');
var users = require('./routes/user.route');
var seeders = require('./routes/seeder.route');
var branches = require('./routes/branch.route');
var companies = require('./routes/company.route');
var dashboard = require('./routes/dashboard.route');
var navigation = require('./routes/navigation.route');
var roles = require('./routes/role.route');
var services = require('./routes/services.route');

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session

require('./routes/auth.route')(app, passport);
app.use('/', index);
app.use('/users', users);
app.use('/seed', seeders);
app.use('/branches', branches);
app.use('/companies', companies);
app.use('/dashboard', dashboard);
app.use('/navigation', navigation);
app.use('/roles', roles);
app.use('/services', services);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  res.status(404).send({ status: 'NOT_FOUND', message: 'This resource is not available.'});
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  let errorObj = { 
    status: 'INTERNAL_SERVER_ERROR',
    message: 'Something went wrong.',
    error: err.message
  };
  res.status(err.status || 500).send(errorObj);
});

module.exports = app;
Run Code Online (Sandbox Code Playgroud)

编辑3

对于那些不了解我的问题的人.用简单的词语解释问题:

  1. My Express服务器在端口3000上运行.
  2. 要从服务器使用任何API,用户必须登录.
  3. 当用户从中登录时localhost:3000,服务器会检查凭据(使用Passport-local)并在响应头中返回一个令牌.
  4. 现在登录后,当用户点击任何API时localhost:3000,预定义Header附带,passport-session然后通行证验证用户会话使用req.isAuthenticated()和所有事情按预期工作.
  5. 当用户从中登录localhost:4000并且服务器在响应头中发送令牌(与之相同localhost:3000).
  6. 成功登录后,用户点击localhost:4000护照js函数req.isAuthenticated()返回的任何API false.
  7. 发生这种情况是因为在跨域cookie中,我们不需要在服务器上设置withCredentials标头到true客户端.
  8. 我已设置withCredentials标题true但仍在req.isAuthenticated()返回的服务器上false.

Ada*_*ler 0

如果您想使用会话(即而不是 jwt 等),我认为默认情况下它们只是在内存中,因此当您的应用程序扩展到多个主机时它将无法工作。不过,将它们配置为持续存在很容易。

请参阅 https://github.com/expressjs/session#completed-session-stores