.net n 层身份和服务架构中的授权
Posted
技术标签:
【中文标题】.net n 层身份和服务架构中的授权【英文标题】:.net n-tier identity & authorization in service architecture 【发布时间】:2011-06-29 23:56:31 【问题描述】:我正在构建一个要求似乎是标准问题的应用程序(至少对我而言)...我有一个基于 asp .net mvc 和来自 iphone、andriod 和 blackberry 的客户端的 Web.UI。
因此,明智的做法是将我所有的业务逻辑转移到可以通过 http 访问的服务层中。该服务层必须接受带有用户上下文(身份)的请求,并以某种不错的方式始终如一地执行授权,无论哪种类型的客户端与其通信(我希望如此?)。
一年多来,我做了一个为期 3 个月的演出,聘请了 W.I.F. (Windows Identity Foundation) 在混合的本地和云架构中。我喜欢它。引起共鸣的 3 件事是 (1) 将身份验证外部化而不关心它是如何完成的,(2) 从业务逻辑中删除授权逻辑,(3) 基于声明的授权。
在过去的一年里,我听说并观看了所有关于 Rest Services 的“新酷嬉皮士做事方式”。所以我虽然很棒,让我们试试看。在我开始玩并开始编码之后,我开始变得非常困惑(随后昨天阅读了大约 10 个小时而没有写另一行 c#)。我仍然对所有 SOAP 与 REST、WS.* 与 Http、SAML 与 SWT 喋喋不休感到困惑。我真的不希望这个线程是关于这个的,因为关于 *** 的发言已经足够多,但我觉得我可以在两个阵营之间做出选择,当我真的不想要一个或另一个时但每个人都有点?
对我来说,我上面提到的关于 WIF 的 3 点似乎不应该与 WS.* 相关联的概念?但我感觉它们,或者至少 WIF 目前是如何产生它们的,没有一些专家的调整(例如,我发现这篇文章是几天前才写的 - http://zamd.net/2011/02/08/using-simple-web-token-swt-with-wif/)。
我不太了解的其他领域是我的客户(iphone、andriod、blackberry)能够使用 WIF,它是否是向他们抛出 SAML 令牌的同一个 STS,它们的行为就像浏览器和就像任何其他客户端一样将它传递回标头?是的,我将不得不找出答案,但如果这是与 W.I.F 的交易破坏者,并且我在发布后立即发现,那么至少我可以专注于它。
最后再加入一件事。我真的不想考虑这些。我想使用第 3 方身份验证/身份提供者 - http://www.janrain.com/products/engage - 我相信它使用 OpenID。这可以融入 W.I.F.还是我只是从 OpenID 创建一个新的 SAML 令牌并从那一刻起使用 WIF。
我想在这段闲聊结束时,我想回到我开始的地方,因为我提出的问题越多,考虑的选项越多,它就会变得越来越复杂。
是否有一个服务层(在 WCF 上)与需要身份上下文和授权的不同非 .net 客户端进行通信,这很奇怪吗?如果你已经构建了这样的东西,你是如何处理它的?
【问题讨论】:
【参考方案1】:当您拥有许多设备时,让相同的解决方案在所有设备上运行的一种方法是针对最小的公分母。
假设您的所有客户端都支持 cookie。一种方法是:
拥有基于 cookie 的身份验证系统。 在服务器端缓存所有授权信息,链接到 cookie 中的会话或密钥 为每个请求检查授权不像使用 SAML 令牌那样优雅,但它确实可以跨平台/设备工作。
iPhone 支持 cookie http://support.apple.com/kb/HT1675
黑莓支持 cookie http://docs.blackberry.com/en/developers/deliverables/11844/feature_cookie_storage_438273_11.jsp
【讨论】:
SAML 令牌只是嵌入在 cookie 中的一种格式......当然它们可以变得非常大,但如果它不是为了爆破而设计的,我不明白为什么不能使用 SAML 令牌跨平台。 为了澄清这一点,我不太关心在客户端上的授权和使用 SAML,我更关心的是服务层的它。我需要知道的是,客户端是否可以像浏览器一样携带令牌。换句话说,我可以假设您在回复中所说的“假设”。 我认为 iphone 应用程序与在您的 iphone 上使用 safari 不一样?我认为您可能会使用它-developer.apple.com/library/ios/#documentation/DataManagement/… ...无论如何,我想知道是否有人真的对更大的图景有所了解。 不,不是,但您是否打算为每个设备创建不同的应用程序。或者您会编写一个可以在所有设备的浏览器中运行的 html5 应用程序? 每台设备上的原生应用程序【参考方案2】:我会稍微抽象一点地回答你的问题......
在开始之前,我的背景偏向 MS,因此其他来源可能有相同(或更好)的选择。
我发现非常有用的两个参考:
1) 基于声明的身份和访问控制指南
http://msdn.microsoft.com/en-us/library/ff423674.aspx
2) 对 Windows Identity Foundation 进行编程
作者:维托里奥·贝托奇 提供kindle格式的硬拷贝
还有很多其他来源,但这两个涵盖了几个场景,并为任何想要跟上您的起点的人提供了很好的背景信息。
我鼓励其他海报填补任何空白或错误:) 我正在掩盖大量技术细节以专注于提出的问题。
我分解联合身份的方式大致如下:
-
应用程序 [应用程序]
身份验证服务 [STS]
索赔集[索赔]
信任关系 [信任]
传输方法[传输]
STS 负责验证用户的身份并为某些声明提供担保。 它通过提供 (1) 包含声明的已签名 blob 或 (2) 第三方可用于查找声明的唯一标识符来实现此目的。
想要为用户提供服务的应用程序可以“信任” STS 向其提供声明,以便与用户进行适当的合作,从而减轻其验证用户的责任(除其他事项外,例如作为维护集中的元数据,但我离题了)。
STS 也有“信任”另一个 STS 的能力,基本上是说“如果你说这个人是 Joe Smith,他们有 X、Y 和 Z 角色,那么我会保证你所说的!”
换个说法:
应用“信任”一个 STS 而后者又可以“信任”另一个 STS 来为其/他们提供声明
** 切换齿轮 **
SOAP 与 REST
归根结底,SOAP 和 REST 都是服务类型,我们称它们为声明消费者。他们都希望有人给他们一个装满索赔的桶,这样他们就可以完成他们的工作并寄回一些东西。 此外,两种服务类型都可以通过使用令牌的查询字符串(假设服务可以处理一些 url 重写)或通过标头(HTTP 用于 REST 和 SOAP 用于 SOAP 服务)来呈现声明。无论哪种方式,目标都是相同的:将声明或 UID 传输到应用程序。
WS* 与 HTTP
这些(连同 TCP/IP、SSL、秘密解码器环等)是来回传递信息的方法,尽管有不同程度的确定性,中间的某个人无法找到冒充用户的方法。
SAML 与 SWT
这些(连同 base 64 编码、xml、简单文本等)都是序列化声明的方法。这两个恰好符合其他人不符合的标准,因此每个人都可以说同一种语言。
** 回到正题**
这些技术组合中的每一种都是有效的(取决于应用程序,有些不太安全,有些更容易实施,有些在较低级别的设备上工作得更好,等等)并且只是一个人的工作方式与另一个人的方式。
因此,如果我有一个 .Net 应用程序,该应用程序通过 WS* 管道获得了一组 SAML 格式的声明,最终结果是该应用程序具有 [SAML 中的声明]。
通过一些处理,这些可以转换为 [SWT 中的声明]。
然后可以将新声明打包并通过 HTTP/SSL 发送到 Java 应用程序。
如果 Java 应用程序“信任”相同的 STS(或“信任”.Net 应用程序 STS 的 STS),那么它会打开声明并执行其工作。
您提到的专家调整必须发生,问题只是由谁进行以及它的透明度如何
-
Dave 提供了一个完全有效的示例,说明使用自定义代码完成调整的一种方法。
ADFS 提供转换规则,尝试通过配置完成合并和转换。
在不同的平台/设备/应用程序/等上提供服务的想法一点也不奇怪,这正是所有这些东西都旨在解决的场景
我正在尝试构建类似于您所询问的内容,因此我自己也一直在处理相同类型的问题。
您提到的 Engage 服务允许您将应用程序的用户与外部来源相关联,并可用于对这些用户进行身份验证... ala “我看到您通过 Google 验证为 John@gmail.com,我知道您是 ID 为 4321 的 John Walker,哦,看,您将 Google 中最喜欢的颜色设置更改为蓝色......继续!”
它不会向您的应用程序提供特定于您的应用程序的声明(除非您需要知道的所有信息都来自 Google 数据,在这种情况下,您可能构建的是混搭而不是 LOB 应用程序。 ..
另一种情况:
-
用户访问您的应用程序
被重定向到您的 STS
被重定向到 Google
已退回您的 STS
添加了电子邮件和最喜欢的颜色声明(每个 google)
已添加角色列表和购买限制声明(来自您的应用程序特定数据存储)
用户返回到应用程序
用户尝试购买 10,000 美元的紫色小部件,而您说“嗯,您只能赊购 5,000 美元,而且...您确定要紫色吗?听说您更喜欢蓝色?”
我要引导您访问的另一个地方是 Microsoft 提供的 AppFabric 访问控制服务。 (http://msdn.microsoft.com/en-us/library/ee732536.aspx) 免责声明:我还没有使用它,但是,它看起来像你正在寻找的那种翻译,为你隐藏了很多肉。
【讨论】:
你能回答***.com/questions/9553267/…吗?【参考方案3】:当 WIF 在后台谈论 WS-Trust / WS-Federation 时,您可以在服务层公开基于声明的身份验证。
本文展示了如何创建一个将使用这些协议与外部客户端通信的 WCF STS。 http://msdn.microsoft.com/en-us/library/ee748498.aspx
从服务层的授权角度来看,您可以使用自定义授权管理器来检查声明是否已提交。 http://msdn.microsoft.com/en-us/library/ms731774.aspx
要插入 OpenID 等外部身份服务并将您自己的声明添加到 WIF 生成的声明中,您可以从 ClaimsAuthenticationManager 子类化,如下所示:
public class MyClaimsAuthenticationManager : ClaimsAuthenticationManager
public override IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal)
if (!incomingPrincipal.Identity.IsAuthenticated)
return incomingPrincipal;
//TODO: obtain user profile claims from external source, i.e. database, web service
// below code demonstrates how to custom claims to the current principal
// (which are then persisted for the lifecycle of the user's browser session)
IClaimsIdentity identity = (IClaimsIdentity)incomingPrincipal.Identity;
identity.Claims.Add(new Claim(ClaimTypes.Email, "dave@dave.com"));
return incomingPrincipal;
您需要通过设置 claimAuthenticationManager 配置参数来告诉 WIF 在 Web.config 文件中使用您自己的声明管理器。
希望这会有所帮助。
【讨论】:
我应该澄清的一点是,我发布的 WCF 授权管理器链接使用了 WCF 声明类,如果您在 WIF 后面部署服务,则应该使用 Microsoft.IdentityModel 命名空间。 【参考方案4】:我已经使用 spring+java 解决了类似的问题;它需要的所有概念都在 .net 中,所以我在这里提到它。我发现spring-security 提出的解决方案效果很好(对于我的简单授权要求)。在我的服务层中,需要特定权限的方法通过注释(在接口或实现上)声明这一点:
@Secured(MyPermissions.READ, MyPermissions.WRITE)
void modifyPerson(PersonChanges changes);
@Secured(MyPermissions.READ)
Person readPerson();
在这个例子中,安全框架 (spring) 使用动态代理包装服务实现,该代理验证我的授权层是否已将正确的线程作用域角色/权限放在评估服务方法的上下文中,如果不是安全的话抛出异常。
我还发现将需要 URL 模式权限的服务组合在一起很有帮助,以便在***别处理“需要经过身份验证的主体”要求:例如myapp/services/secure/personService
-- 如果不存在身份验证信息,任何需要 */secure 的 URL 模式都将重定向到身份验证页面。
要求线程范围凭据的真正好处(我认为)是,即使*** HTTP 拦截器设置错误(例如,无法验证/创建身份验证会话),只要动态代理正常工作业务逻辑无法执行。
此外,它对于聚合服务也非常有效——如果一个服务调用另一个服务,如果它们没有在复合服务上正确声明,则仍然会强制执行较低级别的授权规则。
【讨论】:
以上是关于.net n 层身份和服务架构中的授权的主要内容,如果未能解决你的问题,请参考以下文章