如何通过 Header 传递 JWT 并通过 Sails.js 中的服务器端视图检索数据

How to pass JWT via Header and retrieve data through Server Side Views in Sails.js

后端:Sails.js

我已经为 REST API 实施了 JSON Web 令牌,其中所有 AJAX 请求从 front-end 到各种控制器的操作 return 数据 res.json(data); 仅当它通过授权 Header 收到正确的 JWT 时。它按预期工作。

现在,我已经使用 <%= name => 使用 EJS 创建了一个视图,现在控制器具有详细信息 res.view('/home', {name: "Bill"} ); 并将路由也配置为指向相应的控制器。

我如何通过从具有属性 <%= name =>

的服务器端视图使用已发布的 JWT(存储在 localStorage 中)进行身份验证,从控制器检索 "name"

谢谢。

代码:

views/index.ejs

<%= name =>

api/controllers/UsersController.js

info: function(req, res) {

var userId = req.token;

Users.findOne(userId).exec(function(err, profile) {
    if(err) {
    res.json(err);
    } else {
       res.view('index',{
        name: profile.name,
    });
    }
});        
},

api/policies/tokenAuth.js

module.exports = function(req, res, next) {
  var token;

  if (req.headers && req.headers.authorization) {
    var parts = req.headers.authorization.split(' ');
    if (parts.length == 2) {
      var scheme = parts[0],
        credentials = parts[1];

      if (/^Bearer$/i.test(scheme)) {
        token = credentials;
      }
    } else {
      return res.json(401, {err: 'Format is Authorization: Bearer [token]'});
    }
  } else if (req.param('token')) {
    token = req.param('token');
    delete req.query.token;
  } else {
    return res.json(401, {err: 'No Authorization header was found'});
  }

  sailsTokenAuth.verifyToken(token, function(err, token) {
    if (err) return res.json(401, {err: 'Please Logout and Login again!'});

    req.token = token;

    next();
  });
};

api/services/sailsTokenAuth.js

var jwt = require('jsonwebtoken');

module.exports.issueToken = function(payload) {
  var token = jwt.sign(payload, process.env.TOKEN_SECRET || "xxxxxxx");
  return token;
};

module.exports.verifyToken = function(token, verified) {
  return jwt.verify(token, process.env.TOKEN_SECRET || "xxxxxxx", {}, verified);
};

config/routes.js

module.exports.routes = {
    '/': {
        controller: 'UsersController',
        action: 'info'
      },
};

解决方案:

要使用 JWT 作为从客户端浏览器到服务器的身份验证因素,可以使用 localStorage 或 session cookie。由于在服务器中更容易实现,我最终将范围缩小到使用 cookie。

验证用户身份后,将 JWT 存储在客户端浏览器中,

res.cookie('jwttoken', sailsTokenAuth.issueToken(profile.name));

然后可以使用 req.cookies.jwttoken 检索它并通过服务 (jwt.verify) 验证它以通过 res.jsonres.view[=25 访问请求的信息=]

看不到您的任何代码,因为没有提供,但假设您设置了自定义策略 api/policies/jwt.js 等,并在其中您检查每个请求的 JWTToken。类似的东西(为简单起见忽略任何错误处理):

module.exports = function (req, res, next) {

    var token = req.headers.authorization.split(' ')[1];
    var payload = jwt.decode(token, config.TOKEN_SECRET);
    req.userId = payload.sub;
    next();
};

请注意我是如何将 userId 附加到 req object (req.userId = payload.sub;).这意味着在您的 controller 中,您将有权访问 userId(或者在您的情况下,无论您使用什么 ID 来识别您的登录用户等),因为您可以简单地从传入的 req object 中引用它。

显然,您对 JWT 政策的实施可能会有所不同,但只需将其自定义为上述内容即可。如果您实际上将 name 保留在 jwt 令牌本身中(看不到您的实现),那么只需将其附加到 req object(不需要模型查找)。

获得所需的 name 后,将其传递给您的视图(正如您目前正在使用上面的硬编码值 Bill 所做的那样。

根据更新的问题进行更新

因此,根据您的评论和更新的问题,您已经设法从 JWT 令牌中提取配置文件信息,并从模型查找中获取所需的配置文件信息。您现在无法在 EJS 视图中显示该名称。

所以你可以这样实现:

控制器:

res.view('index', {
        name: profile.name
    }

注意我删除了 profile.name 之后的逗号;)

如果您使用的是模板引擎,

config/views.js 应设置为 "ejs"。

其余看起来不错。至少,符合我的预期。

您最好的选择是显式使用调试器,或者至少 console.log 语句直到 controller.info 方法 returns 之前,并确保 profile.name 按预期设置。如果你做到这一点,那么你就会知道问题出在以某种方式查看的路由上。

您可以尝试在视图下创建一个子文件夹并重命名视图文件(索引有点特殊..)。做一些像 views/xxx/yyy.ejs

也暂时注释掉你的 controller.info 方法,并用一些非常简单的东西代替它,比如:

res.view('xxx/yyy', {
            name: 'bob'
        });

根据进一步的用户反馈进一步更新

从你最后的评论来看,你的问题正在逐渐演变...

我认为您现在要说的是 Sails 代码都可以正常工作,并且使用 Postman 证明可以正常工作。但是在使用 Web 浏览器客户端时失败,因为您的客户端代码没有在 http header.

中传递正确的令牌信息

如果是这种情况,您需要在客户端上创建一个以编程方式应用 header 信息的拦截器。

例如。 (只是取自 Angular 工厂 authInterceptor 的片段,但此处未显示任何 angular 具体内容):

 request: function (config) {
      var token = authToken.getToken();

      if (token) {
        config.headers.Authorization = 'Bearer ' + token;
      }

      return config;
    },

上面,根据请求,从本地存储(你说你正在工作)中检索 JWT,如果令牌存在,则 http headers 信息会使用授权更新 header 形式为'不记名令牌'。

我没有看过你的回购协议,老实说,我确实觉得我已经给了你很多信息。根据我提供的内容,也许再进行一些谷歌搜索/测试,您应该能够获得可行的解决方案。