使用 JWT 和基本身份验证保护 REST 应用程序是否有意义? [英] Does securing a REST application with a JWT and Basic authentication make sense?

查看:18
本文介绍了使用 JWT 和基本身份验证保护 REST 应用程序是否有意义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Spring REST 应用程序,它最初使用基本身份验证进行保护.

然后我添加了一个登录控制器,它创建了一个用于后续请求的 JWT JSON Web 令牌.

我可以将以下代码从登录控制器移到安全过滤器中吗?然后我就不再需要登录控制器了.

tokenAuthenticationService.addTokenToResponseHeader(responseHeaders, credentialsResource.getEmail());

或者我可以删除基本身份验证吗?

将基本身份验证与 JWT 混合使用是一个好的设计吗?

虽然一切正常,但我对如何最好地设计这种安全性一无所知.

解决方案

假设所有通信使用 100% TLS - 在登录期间和登录后的所有时间 - 通过基本身份验证使用用户名/密码进行身份验证并接收 JWT 作为交换是一个有效的用例.这几乎正是 OAuth 2 流程之一(密码授予")的工作原理.

这个想法是通过一个端点对最终用户进行身份验证,例如/login/token 使用您想要的任何机制,并且响应应包含要在所有后续请求中发回的 JWT.JWT 应该是具有适当 JWT 到期 (exp) 字段的 JWS(即加密签名的 JWT):这可确保客户端无法操纵 JWT 或使其寿命超过应有的时间.

您也不需要 X-Auth-Token 标头:HTTP Authentication Bearer 方案是为这个确切的用例创建的:基本上是任何信息跟踪 Bearer 方案名称是应该验证的承载"信息.您只需设置 Authorization 标头:

Authorization: Bearer <JWT value here>

但是,话虽如此,如果您的 REST 客户端不受信任"(例如启用 JavaScript 的浏览器),我什至不会这样做:HTTP 响应中可通过 JavaScript 访问的任何值 - 基本上是任何标头值或响应体值 - 可以通过 MITM XSS 攻击嗅探和拦截.

最好将 JWT 值存储在仅安全、仅 http 的 cookie 中(cookie 配置:setSecure(true)、setHttpOnly(true)).这保证浏览器将:

  1. 只通过 TLS 连接传输 cookie 并且,
  2. 永远不要让 cookie 值可用于 JavaScript 代码.

这种方法几乎是您为获得最佳实践安全性所需要做的一切.最后一件事是确保您对每个 HTTP 请求都有 CSRF 保护,以确保向您的站点发起请求的外部域无法运行.

最简单的方法是使用随机值设置一个仅安全(但不是仅 http)的 cookie,例如一个 UUID.

然后,在对您的服务器的每个请求中,确保您自己的 JavaScript 代码读取 cookie 值并将其设置在自定义标头中,例如X-CSRF-Token 并验证服务器中每个请求的值.外部域客户端无法为您域的请求设置自定义标头,除非外部客户端通过 HTTP 选项请求获得授权,因此任何对 CSRF 攻击的尝试(例如在 IFrame 中)都会失败.

据我们所知,这是当今网络上不受信任的 JavaScript 客户端可用的最佳安全性.Stormpath 写了一篇关于这些技术的文章 如果你很好奇,也可以.呵呵!

I have a Spring REST application which at first was secured with Basic authentication.

Then I added a login controller that creates a JWT JSON Web Token which is used in subsequent requests.

Could I move the following code out of the login controller and into the security filter? Then I would not need the login controller any longer.

tokenAuthenticationService.addTokenToResponseHeader(responseHeaders, credentialsResource.getEmail());

Or could I remove the Basic authentication?

Is it a good design to mix Basic authentication with a JWT?

Although it all works fine, I'm a bit in the dark here as to best design this security.

解决方案

Assuming 100% TLS for all communication - both during and at all times after login - authenticating with username/password via basic authentication and receiving a JWT in exchange is a valid use case. This is almost exactly how one of OAuth 2's flows ('password grant') works.

The idea is that the end user is authenticated via one endpoint, e.g. /login/token using whatever mechanism you want, and the response should contain the JWT that is to be sent back on all subsequent requests. The JWT should be a JWS (i.e. a cryptographically signed JWT) with a proper JWT expiration (exp) field: this ensures that the client cannot manipulate the JWT or make it live longer than it should.

You don't need an X-Auth-Token header either: the HTTP Authentication Bearer scheme was created for this exact use case: basically any bit of information that trails the Bearer scheme name is 'bearer' information that should be validated. You just set the Authorization header:

Authorization: Bearer <JWT value here>

But, that being said, if your REST client is 'untrusted' (e.g. JavaScript-enabled browser), I wouldn't even do that: any value in the HTTP response that is accessible via JavaScript - basically any header value or response body value - could be sniffed and intercepted via MITM XSS attacks.

It's better to store the JWT value in a secure-only, http-only cookie (cookie config: setSecure(true), setHttpOnly(true)). This guarantees that the browser will:

  1. only ever transmit the cookie over a TLS connection and,
  2. never make the cookie value available to JavaScript code.

This approach is almost everything you need to do for best-practices security. The last thing is to ensure that you have CSRF protection on every HTTP request to ensure that external domains initiating requests to your site cannot function.

The easiest way to do this is to set a secure only (but NOT http only) cookie with a random value, e.g. a UUID.

Then, on every request into your server, ensure that your own JavaScript code reads the cookie value and sets this in a custom header, e.g. X-CSRF-Token and verify that value on every request in the server. External domain clients cannot set custom headers for requests to your domain unless the external client gets authorization via an HTTP Options request, so any attempt at a CSRF attack (e.g. in an IFrame, whatever) will fail for them.

This is the best of breed security available for untrusted JavaScript clients on the web today that we know of. Stormpath wrote an article on these techniques as well if you're curious. HTH!

这篇关于使用 JWT 和基本身份验证保护 REST 应用程序是否有意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆