【问题标题】:Authorization header in img src linkimg src 链接中的授权标头
【发布时间】:2018-03-20 10:58:24
【问题描述】:

我有一个api,它使用jwt 进行身份验证。我正在将此 api 用于vuejs 应用程序。我正在尝试使用

在应用程序中显示图像
<img src="my/api/link" />

api 需要Authorization 标头,其中包含jwt token

我可以像这样在浏览器请求中添加标头吗(这里对几个问题的回答让我相信这是不可能的)?

有什么办法解决它(使用 js)还是我应该更改 api 本身?

【问题讨论】:

  • API 应该将图像作为静态资产提供。这不应该需要 JWT 授权。
  • @MaKobi 这是对用例的一个很大的假设。 OP,这个问题的一些相关阅读和潜在解决方案:stackoverflow.com/questions/34096744/…
  • 我需要对图像进行 jwt 授权,因为它们是私有的,只有经过身份验证的用户才能看到它们
  • 你可以使用vue-auth-image插件,以防你使用Vue.js开发
  • JWT 不仅仅是普通的 cookie,这几乎是一个设计缺陷。网络可以正常工作。

标签: javascript html jwt


【解决方案1】:

您不能对直接用作 img 标签中的 href 的图像进行身份验证。如果你真的想对你的图片进行这种类型的身份验证,那么最好使用 ajax 获取它们,然后嵌入到你的 html 中。

【讨论】:

  • 还是这样吗?如果可以,这个答案是否可以接受。
  • 添加这个答案:你甚至不能手动/强制在你的服务工作者fetch处理程序中添加标题。它将在发出实际网络请求之前被删除。
  • 有个链接就好了
【解决方案2】:
<img src="/api/images/yourimage.jpg?token=here-your-token">

在后端,您从 queryparam 验证 JWT。

【讨论】:

  • 但是您的令牌是以纯文本形式发送的,不是吗?
  • @ShafiqueJamal 即使您在 HTTP 标头中包含 JWT,它仍然以明文形式发送。从浏览器使用访问令牌等时始终需要 HTTPS
  • 我不建议这样做,令牌就像密码,如果您的用户复制它然后将其提供给其他人,那么他们可以看到图像。如果用户是恶意的,他们可以使用该令牌从原始用户那里获取更多信息。
  • JWT 在 cookie 中,或者在本地存储中。如果用户是恶意的,那么可以随时使用该令牌。那么 JWT 就不是问题了。
  • 可能的风险:用户右键单击图像并在公共计算机上的另一个选项卡中打开它。他离开了电脑。攻击者进入计算机并开始输入由浏览器自动完成的基本 url(这不是秘密),其参数包含 jwt。
【解决方案3】:

默认情况下,浏览器会发送 cookie。 如果您设置标头的{credentials: 'omit'},您可以阻止在fetch 中发送cookie。 MDN

完整的fetch 示例:

const user = JSON.parse(localStorage.getItem('user'));
let headers = {};

if (user && user.token) {
  headers = { 'Authorization': 'Bearer ' + user.token };
} 

const requestOptions = {
    method: 'GET',
    headers: headers,
    credentials: 'omit'
};

let req = await fetch(`${serverUrl}/api/v2/foo`, requestOptions);
if (req.ok === true) {
...

现在,当您登录时,在您的网站中,webapp 可以保存 将凭据放入 both localStorage 和 cookie。 示例:

let reqJson = await req.json();
// response is: {token: 'string'}
//// login successful if there's a jwt token in the response
if (reqJson.token) {
    // store user details and jwt token in local storage to keep user logged in between page refreshes
    localStorage.setItem('user', JSON.stringify({token: reqJson.token}));
    document.cookie = `token=${reqJson.token};`; //set the cookies for img, etc
}

因此,您的 web 应用程序使用 localStorage,就像您的智能手机应用程序一样。 浏览器默认通过发送 cookie 获取所有静态内容(img、video、a href)。

在服务器端,如果没有,您可以将cookie复制到授权头中。

Node.js+express 示例:

.use(function(req, res, next) { //function setHeader
  if(req.cookies && req.headers &&
     !Object.prototype.hasOwnProperty.call(req.headers, 'authorization') &&
     Object.prototype.hasOwnProperty.call(req.cookies, 'token') &&
     req.cookies.token.length > 0
   ) {
    //req.cookies has no hasOwnProperty function,
    // likely created with Object.create(null)
    req.headers.authorization = 'Bearer ' + req.cookies.token.slice(0, req.cookies.token.length);
  }
  next();
})

我希望它对某人有所帮助。

【讨论】:

  • 当我尝试这个时,requestOptions 出现错误
  • 这是一个聪明的解决方案:在客户端将 jwt 映射到适当的 Web 标准(cookie)并在后端取消映射!
  • 确实很好的解决方案。提醒一下,您必须将 cookie-parser 中间件添加到 express.js 才能使其正常工作。否则,req.cookies 将是未定义的
【解决方案4】:

还有另一种方法将标头添加到 HTTP 请求。是“拦截 HTTP 请求”吗? https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Intercept_HTTP_requests

【讨论】:

  • 注意:这种方法只在firefox浏览器扩展的上下文中有效,不能在网页脚本中使用。
【解决方案5】:

我经常使用的一种解决方法是利用所谓的 nonce API 端点。从经过身份验证的客户端调用此端点时,会生成一个简短的活字符串(可能是一个 guid)(例如 30 秒)并返回。如果您愿意,您当然可以在服务器端将当前用户数据添加到 nonce。

nonce 然后被添加到图像的查询字符串并在服务器端进行验证。此变通办法的成本是额外的 API 调用。但是,变通办法的主要目的是增加安全保证。像魅力一样工作;)。

【讨论】:

    【解决方案6】:

    这是我基于 Tapas 的回答和这个问题How to display Base64 images in HTML? 的解决方案:

    let jwtHeader = {headers: { Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpX..."}
    let r = await axios.get(`/path/image`, {...jwtHeader, responseType:"arraybuffer"});
    let d = Buffer.from(r.data).toString('base64');
    let a = document.createElement('img');
    
    a.src = `data:image/png;base64, ${d}`;
    a.width = 300;
    a.height = 300;
    document.getElementById("divImage").appendChild(a);
    

    在这种情况下,html 将有一个

    【讨论】:

      【解决方案7】:

      您可以使用 Service Worker 拦截 img 获取并在访问服务器之前添加带有 JWT 令牌的 Authorization 标头。描述于:

      【讨论】:

        猜你喜欢
        • 2017-06-23
        • 2015-01-27
        • 1970-01-01
        • 2014-06-22
        • 2018-12-25
        • 2021-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多