当前场景
Spring 项目使用 Spring Security 和 JWT 保护 REST API。这些 API 生成 JSON 响应。 UsernamePasswordAuthenticationFilter
用于验证在 Authorization
中发送的 JWT header 。经过身份验证和未经身份验证的 API 均按预期工作。
要求
现在我需要在 HTTP 响应中为登录用户发送图像。
解决方案1
发送了一个byte[]
,将图像表示为“图像”键 的值 以及其他信息。
但是,如果图像很大,完整的 JSON 响应可能需要一些时间。
解决方案2
将链接作为“图像”键 的值 连同其他信息一起发送。客户可以分配 <img src=the_link>
,它应该在单独的请求中获取大图像。然后用 @RequestMapping
创建一个请求,对应于该链接,它产生一个 byte[]
.
我的问题
我更喜欢解决方案 2。但它会产生UNAUTHORIZED
异常,因为没有有效的 Authorization
token 。此外,此 API 必须经过身份验证。
经过一番查找,发现this ,这与我的要求相同。接受的答案是,
The OAuth Bearer Token spec supports sending the token as a query parameter.
这是我必须做的吗?
- 在我的 Spring 过滤器中,从
Authorization
获取 JWT header ,如果是 空的,从request.getParameter()
获取 - 在第一个 JSON 响应中
API,发送
"image":"http://ip/getImage?token=dbscsbCXV"
- 创建 API
@GetMapping("getImage") byte[] getImage()
或者有什么更好的方法吗? 请指导我。
最佳答案
如果您:
- 为您的服务器使用 HTTPS,否则请求 header 中的 JWT token 将被公开(授权 header 也是如此)。
- 当 token 更改时,不要介意图像 URL 不再有效
另一种方法可能是生成一个具有足够熵的随 secret 钥(例如,将 3 个 UUID 组合成一个字符串)并将其与您的图像实体一起存储,从您的 REST 服务返回它,例如:
https://ip/images/824b6854-edcc-11e6-bc64-92361f0026713567fef0-549a-4cdb-9264-5e15166dfd6f/the-file-name.pdf
确保为这些“公共(public)”路径禁用 Spring 安全过滤器。
这种方法的优点:
- 无需检查此资源的身份验证
- (如果图像变化不大)您可以缓存此内容或通过 CDN 提供内容,而不是每次都访问您的服务器以流式传输图像。
- URL 将继续工作,即使用于身份验证的 JWT token 更改
您可能认为这不如使用每次调用身份验证安全,但如果 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 )
关于java - 使用 Spring security 和 JWT 在 REST 中使用 <img> 标签访问私有(private)图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42105401/