使用HMAC(Play 2.0)保护REST服务

我们有HTTPS,还需要什么?

当您谈论基于REST的API的安全性时,人们通常会指向HTTPS。 借助HTTPS,您可以使用每个人都熟悉的方法轻松保护您的服务免遭窥视。 但是,当您需要更高级别的安全性或HTTPS不可用时,您需要替代方法。 例如,您可能需要跟踪每个客户对API的使用情况,或者需要确切地知道谁在进行所有这些调用。 您可以将HTTPS与客户端身份验证一起使用,但这将需要设置完整的PKI基础结构以及一种安全的方式来标识您的客户并交换私钥。 与基于SOAP的WS-Security服务相比,我们没有可用于REST的标准。

解决此问题的常用方法(Microsoft,Amazon,Google和Yahoo采用此方法)是通过基于客户端与服务之间的共享机密对消息进行签名。 请注意,使用这种方法,我们仅对数据进行签名,而不对数据进行加密。 在这种情况下,我们所讨论的签名通常称为基于哈希的消息认证代码(简称HMAC)。 使用HMAC,我们根据已交换的密钥为请求创建消息认证码(MAC)。

在本文中,我将向您展示如何为基于Play 2.0的REST服务实现此算法。 如果您使用其他技术,则步骤将几乎相同。

HMAC方案

对于客户端,我将仅使用基于HTTPClient的简单应用程序。 要实现这一点,我们必须采取以下步骤:

  1. 首先,我们需要与外部客户端交换共享机密。 通常,这是由API提供程序使用电子邮件发送给客户端的,或者提供程序具有一个您可以在其中查找共享密钥的网站。 请注意,此机密仅在您和服务之间共享,每个客户端将具有不同的共享机密。 这不是像公用密钥那样共享的东西,
  2. 为了确保客户端和服务在同一内容上计算签名,我们需要对要签名的请求进行规范化。 如果我们不这样做,则服务器可能会以与客户端不同的方式解释空格,并得出签名无效的结论。
  3. 基于此规范化消息,客户端使用共享机密创建HMAC值。
  4. 现在,客户端已准备好将请求发送到服务。 他将HMAC值添加到标头中,还将一些内容标识为用户。 例如,用户名或其他公共值。
  5. 当服务收到请求时,它将从标头中提取用户名和HMAC值。
  6. 根据用户名,服务知道应该使用哪个共享密钥对消息进行签名。 例如,该服务将从某处的数据存储中检索此信息。
  7. 现在,服务以与客户端相同的方式对请求进行规范化,并为其自身计算HMAC值。
  8. 如果来自客户端的HMAC与从服务器计算出的HMAC相匹配,则您将知道消息的完整性得到保证,并且客户端就是他所说的身份。 如果提供了错误的用户名,或者使用了错误的机密来计算标题,则HMAC值将不匹配。

要实现HMAC,我们需要做什么? 在以下部分中,我们将研究以下主题。

  • 确定用于输入的字段。
  • 创建可以计算此HMAC的客户端代码并添加相应的标头
  • 创建基于Play 2.0的拦截器来检查HMAC标头

确定输入字段

我们要做的第一件事是确定HMAC计算的输入。 下表描述了我们将包括的元素:

领域 描述
HTTP方法 使用REST,我们执行的HTTP方法定义了服务器端的行为。 对特定URL的删除与对该URL的GET处理不同。
内容MD5 此HTTP标头是标准HTTP标头。 这是请求正文的MD5哈希。 如果我们将此标头包含在HMAC代码生成中,则会获得一个HMAC值,该值会随着请求正文的更改而更改。
Content-Type标头 进行REST调用时,Content-Type标头是重要的标头。 服务器可以根据媒体类型对请求做出不同的响应,因此应将其包含在HMAC中。
日期标题 我们还包括创建请求以计算HMAC的日期。 在服务器端,我们可以确保日期在传输中没有更改。 除此之外,我们可以在服务器上添加消息过期功能。
路径 由于URI标识REST中的资源,因此调用的URL的路径部分也用于HMAC计算。

我们将包括的几乎是来自请求的以下信息:

PUT /example/resource/1
Content-Md5: uf+Fg2jkrCZgzDcznsdwLg==
Content-Type: text/plain; charset=UTF-8
Date: Tue, 26 Apr 2011 19:59:03 CEST

可用于创建HMAC签名的客户端代码

在下面,您可以看到我们用来调用受HMAC保护的服务的客户端代码。 这只是一个基于HTTPClient的快速客户端,我们可以使用它来测试我们的服务。

public class HMACClient {
 
 private final static String DATE_FORMAT = "EEE, d MMM yyyy HH:mm:ss z";
 private final static String HMAC_SHA1_ALGORITHM = "HmacSHA1";
 
 private final static String SECRET = "secretsecret";
 private final static String USERNAME = "jos";
 
 private static final Logger LOG = LoggerFactory.getLogger(HMACClient.class);
 
 public static void main(String[] args) throws HttpException, IOException, NoSuchAlgorithmException {
  HMACClient client = new HMACClient();
  client.makeHTTPCallUsingHMAC(USERNAME);
 }
 
 public void makeHTTPCallUsingHMAC(String username) throws HttpExcept
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值