HTTP基本身份验证而不是TLS客户端认证

Spr*_*ing 26 java security authentication rest web-services

以下答案来自这个问题;

获奖答案实际上并未解决问题.它仅在数据传输的上下文中提及SSL,并不实际涵盖身份验证.

您真的要求安全地验证REST API客户端.除非您使用TLS客户端身份验证,否则SSL本身不是REST API的可行身份验证机制.没有客户端authc的SSL仅对服务器进行身份验证,这与大多数REST API无关.

如果您不使用TLS客户端身份验证,则需要使用类似基于摘要的身份验证方案(如Amazon Web Service的自定义方案)或OAuth甚至HTTP基本身份验证(但仅限于SSL).

因此,考虑到我将使用HTTPS而无需客户端认证 我的问题是海报说如果我们不使用客户端SSL认证服务器并不真正知道它与谁交谈.我在这里理解的是,如果我使用身份验证令牌来访问服务器对客户端进行身份验证.然后,即使该令牌与我的服务器数据库中的用户ID配对,服务器也不知道谁正在发送令牌.

首先

1 - 这是一个真正的问题吗?如果我特别使用Https?(没有TLS客户端身份验证)

2-而且最重要的是,假设这是一个重要的安全缺陷; Http基本身份验证如何在海报中提到帮助?Http基本身份验证只是在标头中发送编码的用户名密码.因此,当客户端收到一个令牌(在他发送用户名密码后作为回报),然后对于其余的请求,他将在此标头中使用此令牌而不是密码,一切都很好吗?

仍然服务器不知道请求来自何处,也许服务器在其数据库中具有匹配用户的有效令牌但未知谁真正发送它.(虽然我仍然很难看到令牌会被https窃取并被其他人使用!)

每当我提出这个问题时,我都会得到答复."嗯..你发送一个令牌,但服务器不知道谁发送令牌,不是很安全"所以我理解这一点,因为浏览器保持一种认证,服务器知道哪里请求来自正确的地方然后我可以确定与该令牌配对的用户(从我的数据库检查)是"非常正确"

或者也许在这里讲的是不正确的

Les*_*ood 73

[海报]说如果我们不使用客户端SSL认证服务器并不真正知道它与谁交谈.

那不是我说的:)这就是我说的:

除非您使用TLS客户端身份验证,否则SSL本身不是REST API的可行身份验证机制.

孤独是这里的关键词.也:

如果您不使用TLS客户端身份验证,则需要使用类似基于摘要的身份验证方案(如Amazon Web Service的自定义方案)或OAuth甚至HTTP基本身份验证(但仅限于SSL).

换句话说,TLS客户端身份验证是验证REST API客户端的一种方法.因为最初的SO问题是关于SSL的,所以我提到如果你单独依赖TLS,TLS客户端authc是唯一的"内置"身份验证形式.因此,如果您正在使用TLS,并且未使用TLS客户端身份验证,则必须使用其他形式的身份验证来验证您的客户端.

有许多方法可以对REST客户端进行身份验证.TLS客户端authc只是其中之一(唯一的'内置'用于TLS,通常非常安全).但是,TLS是一种网络级协议,大多数人认为它太复杂,无法让许多最终用户进行配置.因此,大多数REST API产品都选择使用易于使用的应用程序级协议(如HTTP),因为大多数人都可以使用它(例如,只需设置HTTP标头).

因此,如果您要使用HTTP标头路由,则必须使用标头值来验证REST客户端.

在HTTP身份验证中,您有一个标头Authorization及其值(标头名称相当不幸,因为它通常用于身份验证,而不是通常用于访问控制,即授权).Authorization标头值是服务器用于执行身份验证的标头值,它通常由三个令牌组成

  1. HTTP身份验证方案名称,后跟
  2. 白色空间(几乎总是一个空格字符),然后是
  3. 特定于方案的文本值.

一个常见的HTTP身份验证方案是该Basic方案,它非常......好......基本:).特定于方案的文本值只是以下计算值:

String concatenated = username + ":" + raw_password;
String schemeSpecificTextValue = base_64_encode(concatenated.toCharArray());
Run Code Online (Sandbox Code Playgroud)

所以您可能会看到相应的标题如下所示:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Run Code Online (Sandbox Code Playgroud)

服务器知道如何解析该值.它说:"嘿,我知道这个Basic方案,所以我将采用尾随文本值,base64 解码它,然后我将拥有用户名和提交的密码.然后我可以看到这些值是否与我存储的值相匹配".

而这基本上是Basic身份验证.由于此方案特别包括提交的原始密码base64编码,因此除非您使用TLS连接,否则不会将其视为安全.TLS保证(大多数情况下)窥探眼睛不能拦截标题(例如通过数据包检查)并查看密码是什么.这就是为什么你应该从来不使用HTTP基本身份验证,除非它是通过TLS连接.始终 - 即使在公司内部网环境中也是如此

当然还有其他更安全的HTTP身份验证方案.一个示例是使用基于摘要的身份验证的任何方案.

基于摘要身份验证方案更好,因为他们的方案文本值并没有包含在提交的密码.相反,计算某些数据(通常是其他标题字段和值)的基于密码的哈希值,并将结果放入Authorization标题值中.服务器使用本地存储的密码计算相同的基于密码的哈希.如果服务器的计算值与请求的标头值匹配,则服务器可以认为该请求已通过身份验证.

这就是为什么这种技术更安全的原因:只传输一个哈希 - 而不是原始密码本身.这意味着即使在明文(非TLS)连接上,这种技术也可用于验证请求(但如果请求数据本身当然不敏感,您只想这样做).

一些基于摘要的身份验证方案:

Stormpath和Amazon对于REST比OAuth 1.0a更安全,因为它们始终对请求实体有效负载进行身份验证.OAuth 1.0a仅针对application/x-www-form-urlencoded与使用application/xmlapplication/json有效负载的REST API无关的内容执行此操作(目前这些REST API似乎是大多数REST API).

有趣的是,OAuth2 不是基于摘要的 - 它使用我认为不太安全的东西,称为"持票人令牌",这在我看来是OAuth 2的各种问题的症状.

最后,是的,这是一个无耻的插件,但如果你不想担心这些东西,只需使用Stormpath(许多用例是免费的).我们自动化这些东西,所以你的应用程序不必.

  • @Spring,您可以使用用户密码作为摘要认证的密钥,但通常不建议:如果用户更改了密码,他们的REST客户端将立即中断!最好只有UI登录密码,然后使用REST API密钥(id + secret)进行REST登录(Stormpath就是这样做的).HTH! (2认同)

Ilm*_*nen 10

当我们谈论"验证用户"时,我们真正的意思是"检查用户是否知道其他人不应该知道的事情"."某些东西"可能是密码,证书,硬件安全令牌甚至是用户的视网膜模式,但在所有情况下,它都是我们真正检查的那些信息的访问权限,而不是用户的身份(无论是真的意味着)就这样.

关键在于,原则上,所有这些验证者都可能被窃取并用于冒充用户.可以记录密码,可以从存储的磁盘复制证书,可以窃取硬件令牌(并且可能进行逆向工程和克隆),甚至用户的视网膜图案原则上也可以被扫描,记录和伪造.在每种情况下,我们所能做的最好的事情就是尽可能地"努力".


csc*_*eid 6

也许我误解了这个问题.

你引用的答案告诉我,如果你不使用某种形式的身份验证,无论是客户端证书,HTTP BASICAUTH还是其他什么,服务器都不知道它与谁通信.

(也许这对你的应用来说没问题,也许不是,只有你能回答.)

换句话说,如果您使用某种形式的身份验证,服务器确实知道它与谁通信; 它正在与经过身份验证的凭据所属的"人"进行通信.

在此上下文中,身份验证是通过某些凭据建立身份的过程.

身份验证不保证凭据未被盗.SSL保证(我不会说它"保证")凭证在客户端和服务器之间传输是安全的.

当您使用GMail时,您使用的是SSL,Google如何知道它正在与交谈?