首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >跨域节点js认证

跨域节点js认证
EN

Stack Overflow用户
提问于 2017-11-26 14:41:07
回答 5查看 6.2K关注 0票数 10

我正在开发一个均值应用程序,我在我的项目中使用了角4。对于身份验证,我已经实现了Passport Local-strategy。我正在使用Express-session维护持久会话。在这里之前一切都很顺利。

问题

在同一个域中,session工作得很好,我可以对用户进行身份验证。但在跨领域,我无法维持会话。它为跨域中的每个新请求生成一个新的会话id。

然后我尝试了Passport-jwt,但问题是我无法控制用户会话。我的意思是,如果用户处于非活动状态,甚至在服务器重新启动时,我无法从服务器中注销用户,token也不会失效。

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

我已经看过一些博客文章,比如这样的问题,但是没有帮助。

谢谢。

编辑

我应该编写自己的代码来实现这一点吗?如果是的话我有个计划。

我的基本计划是:

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

我觉得这也是个好主意。我只想要一些建议,不管我是否在正确的方向上思考。

我会从这得到什么:

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

编辑2

在这里,我共享我的app.js代码

代码语言:javascript
复制
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;

编辑3

对那些不了解我问题的人来说。用简单的话来解释这个问题:

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

回答 5

Stack Overflow用户

发布于 2017-12-09 09:09:52

解决CORS/cookie/同域问题的一个可能的解决方案是创建代理服务器,它将镜像从localhost:3000/apilocalhost:4000的所有请求,然后使用localhost:3000/api来访问API而不是localhost:4000

生产部署的最佳方法是在web服务器(nginx/apache)上进行部署。

您也可以通过expressrequest模块在节点中这样做,或者使用一些现成的中间件,比如这个:

https://github.com/villadora/express-http-proxy

使用该中间件的解决方案非常简单:

代码语言:javascript
复制
var proxy = require('express-http-proxy');
var app = require('express')();

app.use('/api', proxy('localhost:4000'));
票数 2
EN

Stack Overflow用户

发布于 2017-12-05 06:52:20

如果您想使用会话(即。我认为在默认情况下,它们只是内存中的,所以它不会像应用程序扩展到多个主机那样工作。不过,很容易将它们配置为持久化。

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

票数 0
EN

Stack Overflow用户

发布于 2017-12-06 05:55:27

你可能试过用护照-jwt。它在登录时根据JWT协议生成令牌。您的要求是在注销时将生成的令牌列入黑名单。为此,您可以在mongodb中创建一个名为"BlacklistToken“的集合,其字段为userid和token。当用户注销时,您可以在集合中插入令牌和userid。然后编写一个中间件来检查令牌是否被列入黑名单。如果它被重定向到登录页面。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47497296

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档