从HttpServletRequest中获取HTTP基本认证
1. 引言
基本认证是HTTP服务最常用的安全机制。其流行源于简单性和易于实现。在本教程中,我们将探讨HTTP基本认证的工作原理,以及如何在基于Spring的应用中从传入的HTTP请求中提取凭据(特别是密码)。
2. HTTP 基本认证
HTTP基本认证是一种简单的认证方案,客户端在HTTP请求头中发送凭据。客户端在请求中包含凭据,放在Authorization头中,然后服务器对其进行验证。头的格式如下:
用户名和密码组合成一个以冒号分隔的字符串。然后使用Base64对该字符串进行编码。例如,如果用户名是admin,密码是secret,则组合字符串为admin:secret。该字符串的Base64编码版本是YWRtaW46c2VjcmV0。最终的HTTP头如下所示:
需要注意的是,Base64是编码,不是加密。它很容易被逆转,因此使用基本认证时必须严格使用HTTPS。
3. Maven 依赖
首先,将spring-boot-starter-web依赖添加到我们的pom.xml中:
4. 从 Authorization 头中检索凭据
在本节中,我们将逐步描述如何从传入的HTTP请求中检索原始用户名和密码。
4.1. 手动从 HTTP 请求中提取
最直接的方法是从HttpServletRequest中直接读取Authorization头并解码。我们来创建一个BasicAuthExtractor类和一个实用方法来执行此操作:
extractCredentials() 方法首先检查Authorization头是否存在,并验证头是否以"Basic "前缀开头。接着,它从头值中移除前缀。然后使用Base64.getDecoder() 解码剩余的Base64编码字符串。解码后,字节被转换为UTF-8字符串。结果字符串应遵循username:password格式。最后,该方法在第一个冒号处分割字符串,返回包含用户名和密码的两个元素数组。如果头无效或格式不正确,则返回null。我们可以轻松地在RestController中使用extractCredentials() 方法:
我们使用@RequestHeader注解从传入请求中获取Authorization头值。
4.2. 自定义 Servlet 过滤器
另一种方法是创建一个自定义Filter,读取头、提取密码,并将其存储在请求属性中以供后续使用。我们来创建一个AuthFilter类来实现此操作:
该过滤器拦截每个传入的HTTP请求,读取Authorization头,然后使用extractCredentials() 方法提取密码,并在继续过滤器链之前将其存储为请求属性。之后,在我们的服务或控制器中,可以安全地检索它:
5. 测试 BasicAuthExtractor
我们先测试核心提取逻辑。首先,需要确保它正确处理有效的Basic认证头,并返回预期的凭据数组:
为了保持测试简洁易读,我们使用一个帮助方法来处理Base64编码和头格式化:
此外,我们需要验证方法对于无效头的处理是否安全返回null,例如缺少Basic前缀或使用不同认证方案的头:
6. 结论
在本文中,我们学习了HTTP基本认证如何对凭据进行编码,以及如何使用Java的Base64工具手动解码它们。我们还探讨了如何使用自定义过滤器捕获原始密码。虽然提取密码在遗留集成中有时是必要的,但由于固有的安全风险,应尽可能避免。一如既往,源代码可在GitHub上获取。