16. Basic and Digest Authentication(基本和摘要式身份验证)
基本认证和摘要认证是网络应用中流行的替代认证机制。基本身份验证通常与无状态客户端一起使用,无状态客户端会在每次请求时传递其凭据。将它与基于表单的身份验证结合使用是很常见的,在这种情况下,应用程序既可以通过基于浏览器的用户界面使用,也可以作为web服务使用。但是,基本身份验证会以纯文本形式传输密码,因此只能在加密传输层(如HTTPS)上使用。
16.1 BasicAuthenticationFilter(基本认证过滤器)
基本身份验证过滤器(BasicAuthenticationFilter)负责处理出现在HTTP头中的基本身份验证凭据。这可用于验证由Spring远程协议(如Hessian和Burlap)以及普通浏览器用户代理(如火狐和互联网浏览器)发出的调用。管理HTTP基本认证的标准由RFC 1945第11节定义,基本认证过滤器符合该RFC。基本身份验证是一种很有吸引力的身份验证方法,因为它在用户代理中部署非常广泛,实现也非常简单(它只是用户名:密码的Base64编码,在一个HTTP头中指定)。
16.1.1 Configuration(配置)
要实现HTTP基本身份验证,您需要向筛选器链添加一个基本身份验证筛选器(BasicAuthenticationFilter )。应用程序上下文应该包含基本身份验证过滤器(BasicAuthenticationFilter )及其所需的协作者:
配置的身份验证管理器(AuthenticationManager )处理每个身份验证请求。如果身份验证失败,将使用配置的AuthenticationEntryPoint重试身份验证过程。通常情况下,您会将过滤器与一个AuthenticationEntryPoint结合使用,该点会返回一个401响应,并带有一个合适的标头,以重试HTTP基本身份验证。如果身份验证成功,生成的身份验证对象将像往常一样放入SecurityContextHolder。
如果身份验证事件成功,或者由于HTTP标头不包含受支持的身份验证请求而未尝试身份验证,则筛选器链将照常继续。只有在身份验证失败并且调用了AuthenticationEntryPoint时,筛选器链才会被中断。
16.2 DigestAuthenticationFilter(摘要式身份验证过滤器)
DigestAuthenticationFilter能够处理在HTTP头中显示的摘要身份验证凭据。摘要式身份验证试图解决基本身份验证的许多缺点,特别是通过确保凭据不会以明文形式通过网络发送。许多用户代理支持摘要式身份验证,包括Mozilla Firefox和互联网浏览器。规范HTTP摘要认证的标准由RFC 2617定义,它更新了RFC 2069规定的摘要认证标准的早期版本。大多数用户代理实现RFC 2617。Spring Security的DigestAuthenticationFilter与RFC 2617规定的“授权”保护质量(qop)兼容,这也提供了与RFC 2069的向后兼容性。如果您需要使用未加密的HTTP(即没有TLS/HTTPS),并且希望最大限度地提高身份验证过程的安全性,摘要式身份验证是一个更有吸引力的选择。事实上,如RFC 2518第17.1节所述,摘要认证是WebDAV协议的一项强制性要求。
您不应该在现代应用程序中使用摘要,因为它被认为不安全。最明显的问题是,您必须以明文、加密或MD5格式存储密码。所有这些存储格式都被认为是不安全的。相反,您应该使用单向自适应密码哈希(即bCrypt、PBKDF2、SCrypt等)。
摘要认证的核心是“nonce”。这是服务器生成的值。 Spring Security’s 的随机数采用以下格式:
DigestAuthenticatonEntryPoint有一个属性指定用于生成nonce令牌的key,以及nonceValiditySeconds属性确定过期时间(默认300,等于5分钟)。只要nonce是有效的,摘要就会通过串联字符串包括用户名,密码,随机数,被请求的URI,一个客户端产生的随机数(仅该用户代理每个请求生成一个随机值),域名等,然后执行MD5哈希值。服务器和用户代理都执行这种摘要计算,如果它们在包含的值(例如密码)上不一致,就会产生不同的哈希代码。在Spring Security实现中,如果服务器生成的随机数刚刚过期(但摘要在其他情况下是有效的),则DigestAuthenticationEntryPoint将发送一个“stale=true”头。这告诉用户代理没有必要打扰用户(由于摘要式身份验证的实现更加复杂,因此经常会出现用户代理问题。例如,在同一个会话中,Internet Explorer无法对后续请求显示“不透明”令牌。因为密码和用户名等是正确的),而只需使用新的随机数重试。
DigestAuthenticationEntryPoint的nonceValiditySeconds参数的适当值取决于您的应用程序。极其安全的应用程序应该注意到,在到达随机数中包含的到期时间之前,可以使用截取的身份验证头来模拟主体。这是选择适当设置时的关键原则,但是对于非常安全的应用程序来说,首先不在TLS/HTTPS上运行是不寻常的。
由于摘要式身份验证的实现更加复杂,因此经常会出现用户代理问题。例如,在同一个会话中,Internet Explorer无法对后续请求显示“不透明”令牌。因此,Spring安全过滤器将所有状态信息封装到“nonce”令牌中。在我们的测试中,Spring Security的实现与Mozilla Firefox和Internet Explorer一起可靠地工作,正确地处理当前超时等。
16.2.1 Configuration(配置)
既然我们已经复习了理论,让我们看看如何使用它。要实现HTTP摘要身份验证,有必要在筛选器链中定义摘要身份验证筛选器。应用程序上下文需要定义DigestAuthenticationFilter及其所需的协作者:
需要已配置的用户详细信息服务,因为DigestAuthenticationFilter必须能够直接访问用户的明文密码。如果您在您的DAO中使用编码密码,摘要式身份验证将不起作用。DAO协作者和用户缓存通常直接与DaoAuthenticationProvider共享。authenticationEntryPoint属性必须是DigestAuthenticationEntryPoint,以便DigestAuthenticationFilter可以为摘要计算获取正确的realmName 和key 。
与基本身份验证过滤器一样,如果身份验证成功,身份验证请求令牌将被放入安全上下文持有者。如果身份验证事件成功,或者由于HTTP标头不包含摘要身份验证请求而未尝试身份验证,则筛选器链将照常继续。只有在身份验证失败并且调用了AuthenticationEntryPoint时,才会中断筛选器链,如前一段所述。
摘要式身份验证的RFC提供了一系列附加功能来进一步提高安全性。例如,随机数可以根据每个请求进行更改。尽管如此,Spring Security实现的目的是将实现的复杂性(以及无疑会出现的用户代理不兼容)降至最低,并避免存储服务器端状态。如果您希望更详细地了解这些特性,请阅读RFC 2617。据我们所知,Spring Security的实现确实符合本RFC的最低标准。
如果将digestauthenticationfilter . passwordreadyencoded设置为true,则可以将密码编码为十六进制格式(MD5(用户名:领域:密码))。但是,其他密码编码不适用于摘要式身份验证。