我正在考虑一个由多个服务/子域组成的web服务设计模型,每个服务/子域可以在不同的平台上实现,并托管在不同的服务器中。
主要问题是身份验证。如果有jane
的资源请求,分离系统可以将该请求作为她的身份进行身份验证吗?
当然,所有服务都访问相同的数据库层。所以我想到了一个单点事实,每个服务都可以用来验证每个请求。
例如,jane
访问www.site.com
,这会在浏览器中呈现内容。浏览器可以向site.com
的不同域发送客户端请求,请求如下:
from internalapi.site.com fetch /user/users_secret_messages.json
from imagestore.site.com fetch /images/list_of_images
身份验证问题是:另一个用户(或局外人)可以制作一个请求,可以欺骗子域,为他们提供他们不应该访问的信息。
所以我想到了一个单点事实:每个服务都可以访问的中央资源,可以用来验证每个请求。
在此伪代码中,AuthService.verify_authentication()
引用中央资源
//server side code:
def get_user_profile():
auth_token=request.cookie['auth_token']
user=AuthService.verify_authentication(auth_token)
if user=Null:
response.write("you are unauthorized/ not logged in")
else:
response.write(json.dumps(fetch_profile(user)))
问题:现有协议,软件甚至是良好的设计实践是否存在多个子域的完美身份验证?
我看到了OAuth如何解决管理第三方访问的麻烦,并想知道这种身份验证是否存在。我也从Kerberos和TACACS获得了这个想法。
这个想法是团队思维的结果,是一种简化架构的方法(而不是处理繁重的负载)。
答案 0 :(得分:1)
我建立了一个不久前做过这个的系统。我们正在建立shop.megacorp.com,并且必须与www.megacorp.com,profile.megacorp.com,customerservice.megacorp.com等共享登录信息。
它的工作方式分为两部分。
首先,所有登录都是通过accounts.megacorp.com上的一组页面处理的。我们页面中的注册链接去了那里,返回URL作为参数(所以https://accounts.megacorp.com/login?return=http://shop.megacorp.com/cart
)。完成后,登录过程将重定向回返回URL。登录页面还设置了一个身份验证cookie,其范围限定为整个megacorp.com域。
其次,通过从请求中获取cookie,然后通过内部Web服务将其转发到accounts.megacorp.com,在各个站点上处理身份验证。我们本可以做到这一点是一个简单的SOAP或REST查询,将cookie作为参数,但实际上,我们所做的是发送一个HTTP请求,并将cookie添加到标题中(就好像用户发送了请求一样)直)。如果cookie有效,该URL将返回为200,提供有关用户的一些信息,如果不是,则提供401或其他信息。然后我们可以相应地处理用户。
毋庸置疑,我们不想为每个用户请求向accounts.megacorp.com发出请求,因此在成功进行身份验证后,我们会将用户的会话标记为已通过身份验证。我们存储cookie值和时间戳,如果后续请求具有相同的cookie值,并且在时间戳的某个超时范围内,我们会将它们视为已通过身份验证而不传递它们。
请注意,因为我们在身份验证请求中将cookie作为cookie传递,所以在accounts.megacorp.com上验证它的代码与处理来自用户的直接请求完全相同,因此正确实现它是微不足道的。因此,为了响应您对“现有协议[或]软件”的需求,我要说协议是HTTP,并且该软件是您可用于验证cookie的任何内容(任何Web容器的用户处理的标准部分)。身份验证服务就像打印用户姓名和详细信息的网页一样简单,并且标记为需要登录用户。
至于“良好的设计实践”,它很有效,并且它非常有效地将登录和身份验证过程与我们的网站分离开来。它确实在accounts.megacorp.com上引入了对服务的运行时依赖性,结果证明它有点不可靠。这很难避免。
实际上,现在我回想一下,对accounts.megacorp.com的请求实际上是一个SOAP请求,我们得到了一个带有用户详细信息的SOAP响应,但正如我所描述的那样,身份验证是用cookie处理的。将它作为REST请求会更简单,更好,我们的系统只是在标准URL上进行了GET,并获得了一些描述用户的XML或JSON。
说了这么多,如果你在应用程序之间共享数据库,你可以只有一个表,在其中记录(用户名,cookie,时间戳)元组,并直接在其中进行查找,而不是发出请求服务。
我能想到的唯一其他方法是使用公钥加密。应用程序处理登录可以使用私钥进行签名,并将其用作cookie。其他应用程序可以具有相应的公钥,并使用它来验证它。密钥可以是每个用户,也可以只有一个。在初始密钥分发之后,这不会涉及应用程序或共享数据库之间的任何通信。