RESTful Web服务-如何验证来自其他服务的请求?

| 我正在设计一个RESTful Web服务,该服务需要用户以及其他Web服务和应用程序访问。所有传入的请求都需要进行身份验证。所有通信均通过HTTPS进行。用户身份验证将基于身份验证令牌进行工作,该身份验证令牌是通过将用户名和密码(通过SSL连接)发布到服务提供的/ session资源中而获得的。 对于Web服务客户端,客户端服务后面没有最终用户。这些请求是由计划任务,事件或某些其他计算机操作启动的。连接服务的列表是事先已知的(显然,我想)。我应该如何验证来自其他(网络)服务的这些请求?我希望对这些服务的身份验证过程尽可能地容易实现,但是不以安全为代价。对于这种情况,标准和最佳做法是什么? 我能想到的(或已向我建议的)选项: 让客户服务诉诸拥有“假”用户名和密码,并以与用户相同的方式对它们进行身份验证。我不喜欢此选项-感觉不正确。 为客户端服务分配一个永久的应用程序ID,也可以分配一个应用程序密钥。据我了解,这与拥有用户名+密码相同。使用此ID和密钥,我可以对每个请求进行身份验证,或者创建身份验证令牌以对其他请求进行身份验证。无论哪种方式,我都不喜欢这个选项,因为任何拥有应用程序ID和密钥的人都可以冒充客户端。 我可以在以前的选项中添加IP地址检查。这将使执行虚假请求变得更加困难。 客户证书。设置我自己的证书颁发机构,创建根证书,并为客户端服务创建客户端证书。不过,我想到了两个问题:a)我如何仍允许用户在没有证书的情况下进行身份验证,以及b)从客户端服务的角度来看,实现此方案有多复杂? 还有什么-那里必须有其他解决方案吗? 我的服务将在Java上运行,但是我故意遗漏了将在其上构建哪种特定框架的信息,因为我对基本原理更感兴趣,而对实现细节却不太感兴趣-我认为这是最好的解决方案无论底层框架如何,都可以实现。但是,我对这个主题没有一点经验,因此,有关实际实现的具体技巧和示例(例如有用的第三方库,文章等)也将不胜感激。     
已邀请:
解决此问题的任何方法都归结为一个共享机密。我也不喜欢硬编码的用户名和密码选项,但是这样做的好处是非常简单。客户证书也不错,但真的有很大不同吗?服务器上有一个证书,客户端上有一个证书。它的主要优点是蛮力更难。希望您有其他保护措施可以防止这种情况的发生。 我认为您很难解决客户端证书解决方案的问题A。您只使用一个分支。
if (client side certificat) { check it } else { http basic auth }
我不是Java专家,并且我从未使用过它来做客户端证书。但是,快速的Google会带我们进入本教程,它看起来正好位于您的小巷。 尽管进行了所有“什么是最好的”讨论,但我还是要指出,还有另一种哲学说:“代码越少,聪明就越好。”(我个人持有这种哲学)。客户端证书解决方案听起来像很多代码。 我知道您表达了有关OAuth的问题,但是OAuth2提案确实包含了针对您的问题的一种解决方案,即“承载者令牌”,该解决方案必须与SSL结合使用。我认为,为简单起见,我会选择硬编码的用户名/密码(每个应用一个),或者选择非常相似的承载令牌。     
阅读完您的问题后,我会说,生成特殊令牌来执行所需的请求。该令牌将在特定的时间(比如说一天)存在。 这是生成身份验证令牌的示例:
(day * 10) + (month * 100) + (year (last 2 digits) * 1000)
例如: 2011年6月3日
(3 * 10) + (6 * 100) + (11 * 1000) = 
30 + 600 + 11000 = 11630
然后连接用户密码,例如\“ my4wesomeP4ssword!\”
11630my4wesomeP4ssword!
然后执行该字符串的MD5:
05a9d022d621b64096160683f3afe804
何时调用请求,请始终使用此令牌,
https://mywebservice.com/?token=05a9d022d621b64096160683f3afe804&op=getdata
这个令牌每天都是唯一的,因此我想这种保护足以永远保护我们的服务。 希望有所帮助 :)     
您可以采用几种不同的方法。 RESTful的纯粹主义者将希望您使用BASIC身份验证,并在每次请求时发送凭据。他们的理由是没有人存储任何状态。 客户端服务可以存储cookie,该cookie维护会话ID。我个人认为这并不像我听到的一些纯粹主义者那样令人反感-一次又一次地进行身份验证可能会很昂贵。听起来您似乎不太喜欢这个主意。 从您的描述来看,这听起来确实像您对OAuth2感兴趣。到目前为止,据我所知,这是一种令人困惑的过程,并且是一种前沿技术。那里有很多实现,但是它们之间相差无几。在Java中,我知道它已经集成到Spring3的安全模块中。 (他们的教程写得很好。)我一直在等待,看看Restlet中是否会有扩展,但是到目前为止,尽管已经提出了扩展,并且可能在孵化器中,但仍然没有已完全合并。     
我相信这种做法: 第一次请求,客户端发送ID /密码 交换ID /通行证以获得唯一令牌 在每个后续请求上验证令牌,直到令牌过期 不管您如何实施以及其他特定的技术细节,它都是非常标准的。 如果您真的想推信封,也许您可​​以将客户端的https密钥视为暂时无效的状态,直到验证凭据为止;如果凭据从未验证过,则限制信息;在验证凭据时再次基于到期授予访问权限。 希望这可以帮助     
就客户端证书方法而言,实现它并不困难,同时仍然允许没有客户端证书的用户进入。 如果实际上您确实创建了自己的自签名证书颁发机构,并为每个客户服务颁发了客户证书,那么您将有一种简单的方式来验证那些服务。 根据所使用的Web服务器,应该有一种方法可以指定将接受客户端证书但不需要证书的客户端身份验证。例如,在Tomcat中指定https连接器时,可以设置\'clientAuth = want \',而不是\'true \'或\'false \'。然后,您将确保将自签名的CA证书添加到您的信任库中(默认情况下,除非您在Web服务器配置中指定了另一个文件,否则您正在使用的JRE中的cacerts文件),因此唯一受信任的证书将是那些由您自己签署的CA。 在服务器端,仅当您能够从请求中检索客户端证书(不为null)时,才允许访问您想要保护的服务,并在需要任何额外安全性时通过任何DN检查。对于没有客户端证书的用户,他们仍然可以访问您的服务,但在请求中将不包含任何证书。 我认为这是最“安全”的方式,但是它肯定有其学习曲线和开销,因此不一定是满足您需求的最佳解决方案。     
5.还有其他东西-那里必须有其他解决方案吗? 您说得对,有!它被称为JWT(JSON Web令牌)。 JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用HMAC算法)或使用RSA的公/私钥对对JWT进行签名。 我强烈建议您研究JWT。与替代解决方案相比,它们是解决问题的简单得多的解决方案。 https://jwt.io/introduction/     
您可以在服务器上创建会话,并通过每个REST调用在客户端和服务器之间共享“ 6”。 首先认证REST请求:“ 7”。返回带有
sessionId: ABCDXXXXXXXXXXXXXX
的响应(根据您的客户端格式); 将此
sessionId
与实际会话一起存储在actual10 actual中。
Map.put(sessionid, session)
或使用
SessionListener
为您创建和销毁密钥;
public void sessionCreated(HttpSessionEvent arg0) {
  // add session to a static Map 
}

public void sessionDestroyed(HttpSessionEvent arg0) {
  // Remove session from static map
}
在每个REST调用中获取sessionid,例如
URL?jsessionid=ABCDXXXXXXXXXXXXXX
(或其他方式); 使用
sessionId
从地图中检索
HttpSession
; 如果会话处于活动状态,则验证对该会话的请求; 发回响应或错误消息。     
一旦用户批准请求,我将使用一个应用程序使用应用程序id参数将用户重定向到您的网站,该请求将生成一个唯一的令牌,供其他应用程序用于身份验证。这样,其他应用程序不会处理用户凭据,并且其他应用程序可以由用户添加,删除和管理。 Foursquare和其他一些站点通过这种方式进行身份验证,并且与其他应用程序一样非常易于实现。     
除了身份验证,我建议您考虑一下全局。考虑使您的后端RESTful服务无需任何身份验证;然后在最终用户和后端服务之间放置一些非常简单的身份验证所需的中间层服务。     

要回复问题请先登录注册