使用Spring security和JWT在REST中使用<img>标记访问私有映像

Ram*_*n R 8 java rest spring oauth spring-security

目前的情景

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

需求

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

解决方法1

发送a byte[],将图像表示为"图像" 以及其他信息.但是,如果图像很大,这可能需要一些时间才能完成JSON响应.

溶液2

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

我的问题

我更喜欢Solution2.但它会产生UNAUTHORIZED异常,因为没有有效的Authorization令牌.此外,必须对此API进行身份验证.

经过一番搜索,发现了这一点,这与我的要求相同.接受的答案说,

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

这是我必须做的吗?

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

或者有更好的方法吗?请指导我.

Fre*_*ans 6

如果你:你的建议包括令牌似乎没问题

  • 对服务器使用HTTPS,否则请求标头中的JWT标记是公开的(授权标头也是如此).
  • 令牌更改时,请不要介意图片网址不再有效

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

https://ip/images/824b6854-edcc-11e6-bc64-92361f0026713567fef0-549a-4cdb-9264-5e15166dfd6f/the-file-name.pdf
Run Code Online (Sandbox Code Playgroud)

确保为这些"公共"路径禁用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)