【问题标题】:How to pass JWT via Header and retrieve data through Server Side Views in Sails.js如何通过 Header 传递 JWT 并通过 Sails.js 中的服务器端视图检索数据
【发布时间】:2016-04-21 03:42:37
【问题描述】:

后端:Sails.js

我已经为 REST API 实现了 JSON Web Token,只有当它通过 Authorization Header 接收到正确的 JWT 时,从前端到各种控制器的操作的所有 AJAX 请求才会返回数据res.json(data);。它按预期工作。

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

如何通过使用属性 <%= name => 的服务器端视图中已发布的 JWT(存储在 localStorage 中)进行身份验证,从控制器中检索“名称”

谢谢。

代码:

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 或会话 cookie。由于在服务器中更容易实现,我终于将其范围缩小到使用 cookie。

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

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

然后可以使用req.cookies.jwttoken 检索它并通过服务 (jwt.verify) 对其进行验证,以通过res.jsonres.view 访问请求的信息

【问题讨论】:

    标签: node.js express sails.js jwt express-jwt


    【解决方案1】:

    看不到您的任何代码,因为未提供,但可以说您设置了自定义策略 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 对象(req.userId = payload.sub;)。这意味着在您的 controller 中,您将可以访问 userId(或者在您的情况下,您可以使用任何 id 来识别您的登录用户等),因为您可以简单地从传入的 req 对象中引用它。

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

    获得所需的name后,将其传递给您的视图(就像您目前对上面的硬编码值Bill所做的那样。

    根据更新后的问题进行更新

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

    所以你可以达到这样的效果:

    控制器:

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

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

    config/views.js 如果您使用的模板引擎应该设置为“ejs”。

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

    最好的办法是显式使用调试器,或者至少在 controller.info 方法返回之前使用 console.log 语句,并确保按预期设置 profile.name。如果你走得那么远,那么你就会知道问题在于以某种方式查看的路由。

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

    同时暂时注释掉你的 controller.info 方法,并将其替换为非常简单的内容,例如:

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

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

    从您上次的评论来看,您的问题正在逐渐演变......

    我认为您现在所说的是 Sails 代码都可以正常工作,并且使用 Postman 证明可以正常工作。但是在使用 Web 浏览器客户端时失败,因为您的客户端代码未在 http 标头中传递正确的 Token 信息。

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

    例如。 (只是从 Angular 工厂 authInterceptor 中提取的一个 sn-p,但这里没有显示特定的角度):

     request: function (config) {
          var token = authToken.getToken();
    
          if (token) {
            config.headers.Authorization = 'Bearer ' + token;
          }
    
          return config;
        },
    

    上面,根据请求,从本地存储中检索 JWT(你说你已经工作了),如果令牌存在,则使用 'Bearer token 形式的授权头更新 http 头信息'。

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

    【讨论】:

    • 非常感谢您的回答。我添加了带有问题的代码示例。就像你说的那样,我已经在 J​​WT 机密中实现了 userId,并且可以很好地用于 REST API 调用。就像客户端/前端使用带有 JWT 令牌的授权标头请求信息一样,然后使用 req.token 在后端(控制器/操作)中接收它,该信息将转换为用于处理请求信息的用户 ID。但我很困惑的是如何从服务器端视图中检索相同的信息。
    • 我真正想做的事情:1.登录视图:获取用户ID和密码->生成JWT->将其存储在用户浏览器的localStorage 2.重定向到配置文件视图(只有具有有效JWT的用户可以访问它)在使用 AJAX 调用访问时,它按预期工作我可以使用“res.json”获取信息,但我想使用“res.view”而不是使用服务器端视图而不使用 AJAX 请求,因为这些 *. ejs 文件已经驻留在服务器中。
    • 我已经创建了一个 repo:github.com/vijayrajasekaran/sails-auth-jwt 我可以在视图中获取名称:bob,并且控制器禁用了 JWT。当我使用授权标头(JWT 令牌)传递 REST API 调用时,它也适用于启用 JWT 但无法理解,我如何让用户在成功登录后进行身份验证并让他浏览受 JWT 保护的多个视图,因为我没有发送Authorization 标头作为 REST API 调用以获取请求的信息。使用 localhost/profile 直接访问视图时,显示“No authorization header”。
    • 场景(对于我在 GitHub 中添加的存储库): 1. 用户在其浏览器的 localStorage 中拥有 JWT 2. 当他访问时,localhost:1337/profile 3. 他应该得到一个呈现为“名称: smith'.. 使用 Postman REST Client/jQuery AJAX 调用和 Authorization Header: Bearer 'token' 进行 REST API 调用时效果很好
    • @VijayRajasekaran - 更新了我的答案 - 请注意我没有时间查看您的回购。如果您发现信息对您有帮助,请支持/将我的答案标记为正确,不胜感激。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-04
    • 1970-01-01
    • 2019-04-23
    • 2016-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多