我有一个Spring REST应用程序,该应用程序最初是通过基本身份验证来保护的。

然后,我添加了一个登录 Controller ,该 Controller 创建了一个JWT JSON Web token ,该 token 在后续请求中使用。

我可以将以下代码从登录 Controller 中移出并移至安全过滤器中吗?然后,我将不再需要登录 Controller 。

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

还是可以删除基本身份验证?

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

尽管一切正常,但为了最好地设计此安全性,我在这里还是有些困惑。

最佳答案

假设所有通信(登录期间和登录后始终)的TLS均为100%,则通过基本身份验证使用用户名/密码进行身份验证并以交换方式接收JWT是有效的用例。这几乎就是OAuth 2流程(“密码授予”)的工作方式。

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

您也不需要X-Auth-Token header :就是为这个确切的用例创建的HTTP身份验证Bearer方案:跟踪Bearer方案名称的任何信息基本上都是应该验证的“承载”信息。您只需设置Authorization header :

Authorization: Bearer <JWT value here>

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

最好将JWT值存储在仅安全,仅HTTP的cookie中(cookie配置:setSecure(true),setHttpOnly(true))。这保证了浏览器将:
  • 仅通过TLS连接传输cookie,并且
  • 永远不会使cookie值可用于JavaScript代码。

  • 这种方法几乎是实现最佳实践安全性所需执行的所有操作。最后一件事是确保对每个HTTP请求都具有CSRF保护,以确保对您的站点发起请求的外部域无法正常运行。

    最简单的方法是设置一个具有随机值(例如,一个UUID。

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

    我们知道,这是当今可用于网络上不受信任的JavaScript客户端的最佳安全性。如果您好奇,Stormpath也会在these techniques上写文章。

    最终,Stormpath Java Servlet Plugin已经为您完成了所有这一切(还有很多很酷的工作,包括其他自动​​安全检查),因此您不必编写它-或更糟的是自己维护它。查看HTTP Request Authentication section和Form / Ajax示例,以了解如何使用它。 HTH!

    10-07 19:34
    查看更多