当前场景
一个 Spring 项目使用 Spring 安全性和 JWT 保护 REST API。这些 API 生成 JSON 响应。实现UsernamePasswordAuthenticationFilter
用于验证在标头中发送Authorization
JWT。经过身份验证和未经身份验证的 API 都按预期工作。
要求
现在我需要在HTTP响应中为登录用户发送图像。
解决方案1
发送了一个byte[]
,将图像表示为"图像">键的值以及其他信息。 但是,如果图像很大,则可能需要一些时间才能完成完整的 JSON 响应。
解决方案2
已将链接作为值发送到"图像">键以及其他信息。客户端可以分配<img src=the_link>
,这将应该在单独的请求中获取大图像。然后创建一个带有@RequestMapping
的请求,对应于该链接,这将产生一个byte[]
。
我的问题
我更喜欢解决方案2。但它会产生UNAUTHORIZED
异常,因为没有有效的Authorization
令牌。此外,此 API 必须经过身份验证。
经过一番搜索,发现了这一点,这与我的要求相同。接受的答案说,
OAuth 持有者令牌规范支持将令牌作为查询参数发送。
这是我必须做的吗?
- 在我的 Spring 过滤器中,从
Authorization
标头中获取 JWT,如果是 空的,从request.getParameter()
中获取 - 在第一个的 JSON 响应中 API,发送
"image":"http://ip/getImage?token=dbscsbCXV"
- 创建 API
@GetMapping("getImage") byte[] getImage()
还是有更好的方法? 请指导我。
如果您
:- 对服务器使用 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 提供内容,而不是每次都只为流式传输图像而访问您的服务器。
- URL 将继续工作,即使用于身份验证的 JWT 令牌发生变化
您可能认为这不如使用每次调用身份验证安全,但如果 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)