我正在开发 REST API,但如果不使用自签名证书,我将无法使用 HTTPS 。我知道这对某些人来说可能是可以接受的,但我不希望在客户端浏览器上弹出安全消息。
在网络上传递的信息不敏感,所以我不关心窃听,但我想确保只有授权的客户端才能发出请求并防止重放攻击。这是我的想法:
用户注册到运行服务的 Web 应用程序。他们想注册一个 API 客户端,但他们不是开发人员,因此他们下载了提供的客户端应用程序(在本例中,他们将与计算机一起使用的 IC 卡读卡器,该计算机可以将从扫描卡读取的数据传送到 Web 服务通过 API)。
第一步:API 客户端应用程序生成一个密钥对(例如 OpenSSL)并将公钥发送到服务器(当用户向服务器注册客户端时,这可以是手动上传步骤)。服务器将公钥存储在与用户相关联的数据库中以及客户端的描述(例如“PC01 上的IC 卡读卡器”)中。
为什么要使用密钥对(如 SSH)?我觉得共享秘密很容易被窃听,因为它必须至少通过网络传输一次。虽然可以通过在服务器终端上手动输入密钥而不是通过网络传输密钥来防止这种情况,但系统的一个设计目标是允许我自己以外的用户注册客户端并使用 Web 界面获取 API 访问令牌应用。在这种情况下,窃听者可以截获共享密钥,而客户端生成的密钥对会阻止这种情况。
第二步:当发出请求时,客户端首先从服务器获取一个随机数(将它存储在随机数列表或数据库中并发布时间戳),然后在使用他们的私钥签署请求时发出包括随机数的请求。服务器在执行请求之前验证消息是真实的(由客户端签名,没有其他人签名)。
我使用这种方法的目标是确保只有有效的客户端才能访问 API,同时还可以防止重放攻击。攻击者应该能够看到消息的内容(不是很敏感),但应该无法修改它们。客户端并不真正关心来自服务器的数据是否真实(因为在这种情况下,客户端正在更改服务器的状态,而不是相反)。
- 这种方法是否满足这些设计目标?
- 它是否可以防止中间人攻击(假设客户端的原始注册是使用真实服务器而不是攻击者的假服务器)?