使用 Spring 安全性和 JWT 在 REST 中使用 <img> 标签访问私有图像

Posted

技术标签:

【中文标题】使用 Spring 安全性和 JWT 在 REST 中使用 <img> 标签访问私有图像【英文标题】:Access private images with <img> tag in REST with Spring security & JWT 【发布时间】:2017-06-25 14:45:53 【问题描述】:

当前情景

Spring 项目使用 Spring Security 和 JWT 保护 REST API。这些 API 产生 JSON 响应。 UsernamePasswordAuthenticationFilter 用于验证在 Authorization 标头中发送的 JWT。经过身份验证和未经身份验证的 API 都按预期工作。

要求

现在我需要在 HTTP 响应中为登录用户发送图像。

解决方案1

发送一个byte[],将图像表示为到“图像”以及其他信息。 但是,如果图像很大,完整的 JSON 响应可能需要一些时间。

解决方案2

将链接作为发送到“图像”以及其他信息。客户端可以分配&lt;img src=the_link&gt;,它将在单独的请求中获取大图像。然后创建一个带有@RequestMapping 的请求,对应于该链接,生成一个byte[]

我的问题

我更喜欢解决方案 2。但它会产生UNAUTHORIZED 异常,因为没有有效的Authorization 令牌。此外,此 API 必须经过身份验证。

经过一番搜索,找到了this,和我的要求一样。接受的答案说,

OAuth Bearer Token 规范支持将令牌作为查询参数发送。

这是我必须做的吗?

在我的 Spring 过滤器中,从 Authorization 标头获取 JWT,如果是 空,从request.getParameter()获取 在第一个 JSON 响应中 API,发送"image":"http://ip/getImage?token=dbscsbCXV" 创建 API @GetMapping("getImage") byte[] getImage()

或者有没有更好的方法? 请指导我。

【问题讨论】:

【参考方案1】:

如果您:

为您的服务器使用 HTTPS,否则请求标头中的 JWT 令牌会暴露(授权标头也是如此)。 不要介意图像 URL 在令牌更改时不再起作用

另一种方法可能是生成具有足够熵的随机密钥(例如,将 3 个 UUID 组合成一个字符串)并将其与您的 Image 实体一起存储,从您的 REST 服务返回,例如:

https://ip/images/824b6854-edcc-11e6-bc64-92361f0026713567fef0-549a-4cdb-9264-5e15166dfd6f/the-file-name.pdf

确保为这些“公共”路径禁用 Spring 安全过滤器。

这种方法的优点:

无需检查此资源的身份验证 (如果图像没有太大变化)您可以缓存此内容或通过 CDN 提供内容,而不是每次都访问您的服务器以获取流式图像。 即使用于身份验证的 JWT 令牌发生更改,URL 也会继续工作

您可能认为这不如使用按呼叫身份验证安全,但如果 ID 有足够的熵,它是防水的。 Facebook 也使用了这个概念(https://www.quora.com/Are-Facebook-pictures-really-private-and-are-they-hosted-on-Facebook-servers、https://en.wikipedia.org/wiki/Capability-based_security)

【讨论】:

感谢@FrederikHeremans。在尝试您的建议并参考链接后会回来。

以上是关于使用 Spring 安全性和 JWT 在 REST 中使用 <img> 标签访问私有图像的主要内容,如果未能解决你的问题,请参考以下文章

来自 Spring Rest 控制器中 JWT 的安全决策

Spring(Websockets / REST / Security)、JWT 和 Sockjs(Stomp)集成

使用 Spring Boot 和 JWT 保护 REST Api

Spring 安全 SAML OpenAM

在 Spring Boot 中使用 Keycloak 实现 JWT、JWE 和 JWS(签名 JWT)

使用 @PreAuthorize 的 GraphQL 和 Spring Security?