首页开发者平台

ASP.NET 跨站、跨应用程序身份认证
出自 paioa.com  2020-1-1

本文作者:架构狮 小A

本文中,笔者将通过研究和自己的实践来总结我对 ASP.NET 跨站、跨应用程序 身份认证的理解,希望对有需要的 .NET 程序员有些帮助。

1、Cookie 和域名级别的关系

由于安全原因,Cookie 被限制在某个域名级别。根据FRC 2901和2965,不能将 Cookie 设置为 .com,.org,.gov 等顶级域名。所需的最低域级别是第二级。
例如,paioa.com(二级)和 public.paioa.com(三级)都可以设置 Cookie。第三层以上的域通常被称为“子域”。
www.paioa.com,public.paioa.com 都是二级域名 paioa.com 的子域名。
设置为二级域名的 Cookie 在其所有第三级域名都可见。但是,设置为第三级域的 Cookie 在其父级二级域和其他子域中不可见。
如果在写入 Cookie 时未指定域名,则 Cookie 的域属性默认为应用程序所在的域名。
例如,如果 Cookie 由 public.paioa.com 设置,而未指定域属性,则 Cookie 的域将默认为 public.paioa.com。
因此,Cookie 只会在这个特定的子域  public.paioa.com 中可见。在 me.paioa.com 或 paioa.com 的其他子域中不可见。

2、ASP.NET 表单身份验证 Cookie

ASP.NET 通过一个安全加密的文本字符串的 Forms 身份验证票据跟踪用户。该票据在 Web 服务器和客户端浏览器之间来回传递,以保持用户身份验证状态。在登录期间,用户的凭证首先会针对数据存储进行验证,然后调用 FormsAuthentication.SetAuthCookie 方法(或其他方法)将用户登录到应用程序中。
此方法调用将生成一个 Forms 身份验证票证,同时创建一个 Forms 身份验证 Cookie 来存储票证。
换句话说,成功验证后,ASP.NET 将创建一个具有 Forms 身份验证票证值的 Forms 身份验证 Cookie。
票据和 Cookie 都是由框架安全加密的。

请注意,身份验证票据通常保存到 Cookie 中,除非 ASP.NET 应用程序被指定为“无Cookie”,在这种情况下,票据将由框架附加到 URL。这不在本文讨论的范围。

ASP.NET 表单认证的用户票证判断和获取通过下列代码。

if (User.Identity.IsAuthenticated)
 Response.Write(User.Identity.Name);

3、在同一个域名下的单点登录

由于 Forms 身份验证是通过 Forms 身份验证票证完成的,因此,如果所有应用程序共享一个身份验证票证,则只需要登录一次,即单点登录。
假设我们有一个网站 oa.paioa.com,MyApp 是网站 oa.paioa.com 下的一个独立的【应用程序】,使用独立应用程序池,不要和虚拟目录混淆。
如下图所示:

正如你所看到的,
http://oa.paioa.com
http://oa.paioa.com/MyApp/
它们是同一子域 oa.paioa.com 下的两个应用程序 。 主站 oa.paioa.com 写的 Cookie 将会被 MyApp 看到。
但是,这并不意味着当用户登录到 oa.paioa.com 时,他会自动登录到 MyApp。
原因是每个 ASP.NET 应用程序默认使用自己的加密密钥来创建 Forms 身份验证票证和 Cookie。因此,oa.paioa.com 编写的 Cookie 无法被 MyApp 成功读取,即使它对MyApp 可见。

如何才能使这两个应用程序识别对方的 Ticket 和 Cookie?
事实上,在 ASP.NET 中它非常简单。 唯一需要做的是更改 web.config 的<machineKey>元素。
以下是 machinKey 的默认设置,或者你的 web.config 根本没有 machineKey 配置代码。

<machineKey validationKey="AutoGenerate,IsolateApps" decryptionKey="AutoGenerate,IsolateApps" validation="SHA1" decryption="Auto" />

通过这些设置,.NET 框架使用自动生成的来创建身份验证票证和 Cookie。 每个应用程序使用不同的键 。
为了使多个应用程序共享相同的身份验证票证和 Cookie,我们只需要在所有应用程序中将 validationKey 和 decrytionKey 设置为相同的值,validation 和 decryption 保持一致。
类似于以下内容:

<machineKey validation="SHA1" decryption="DES" decryptionKey="B9B1431177328B7CCD1CD35D6628C9072A7069FD3BFC8790" validationKey="252B1F96CEF257C94A8829492E6C685AB09E0F817D453F2C6C54EB82F3CEAE83114652334B1E85DD29BB8077C052977C114711EA7775FED06144AFFD44542274" />


要生成上面的密钥,您可以使用【IIS管理】的【计算机密钥】功能,获得的计算机密钥可以立即【应用】保存到 web.config 文件中。

打开IIS管理器 >>选择网站或应用程序,选择【计算机密钥】,点击【生成密钥】,生成后点击【应用】,密钥会保存在当前网站或应用程序下的 web.config 里面。
如下图所示:


4、二级域名下的单点登录

由于业务和管理需要,通常会看到来自同一组织的多个不同子域。
http://oa.paioa.com
http://me.paioa.com

它们都是同一个二级域名 paioa.com 下的三级域名(子域名)。假设所有应用程序都有计算机密钥正确设置为单点登录,如上一节所述。但是,您会发现单点登录无效。
在 oa.paioa.com 上登录的用户仍然需要在 me.paioa.com 上登录。
这是因为在登录时,在 oa.paioa.com 中创建的身份验证 Cookie 默认情况下具有 oa.paioa.com 的域属性,这对 me.paioa.com 不可见。

要使认证 Cookie 在所有其他子域中可见,我们需要修改 Cookie 的域属性以指向其第二级域 paioa.com。下面的代码就是这样做的。
这种修改使得二级域名 paioa.com 内的单点登录成为现实。

通常的 ASP.NET 表单认证的 Cookie 创建方法,这样的写法,没有设置子域,默认为应用程序的子域。
其实这种写法,我们可以通过 web.config 设置 Cookie 的域名。

FormsAuthentication.SetAuthCookie(txtUserName.Text, false);


通过 web.config 设置 Cookie 的二级域名

<authentication mode="Forms">
 <forms domain="paioa.com" defaultUrl="/" loginUrl="index.aspx" Cookieless="UseCookies" timeout="2880" />
</authentication>

 

创建一个自定义二级域名的 Cookie

System.Web.HttpCookie MyCookie = System.Web.Security.FormsAuthentication.GetAuthCookie(User.Identity.Name.ToString(), false);
MyCookie.Domain = "paioa.com"; //修改这里的二级域名
Response.AppendCookie(MyCookie);

 

下面的示例代码包括三个部分:
(1) oa.paioa.com 的 web.config 代码。
我们在 ASP.NET 表单认证配置了域属性 domain="paioa.com"。

<authentication mode="Forms">
 <forms domain="paioa.com" defaultUrl="/" loginUrl="index.aspx" Cookieless="UseCookies" timeout="2880" />
</authentication>
<machineKey validation="SHA1" decryption="DES" decryptionKey="B9B1431177328B7CCD1CD35D6628C9072A7069FD3BFC8790" validationKey="252B1F96CEF257C94A8829492E6C685AB09E0F817D453F2C6C54EB82F3CEAE83114652334B1E85DD29BB8077C052977C114711EA7775FED06144AFFD44542274" />

 

(2) MyApp 应用程序的 web.config 代码。

<authentication mode="Forms">
 <forms Cookieless="UseCookies" timeout="2880" />
</authentication>
<machineKey validation="SHA1" decryption="DES" decryptionKey="B9B1431177328B7CCD1CD35D6628C9072A7069FD3BFC8790" validationKey="252B1F96CEF257C94A8829492E6C685AB09E0F817D453F2C6C54EB82F3CEAE83114652334B1E85DD29BB8077C052977C114711EA7775FED06144AFFD44542274" />

 

(3) me.paioa.com 的 web.config 代码。
请注意这里的 domain 我们设置了 me.paioa.com,在 oa.paioa.com 登录的身份验证 Cookie(域属性 paioa.com)在子域名 me.paioa.com 中可见。

<authentication mode="Forms">
 <forms domain="me.paioa.com" Cookieless="UseCookies" timeout="2880" />
</authentication>
<machineKey validation="SHA1" decryption="DES" decryptionKey="B9B1431177328B7CCD1CD35D6628C9072A7069FD3BFC8790" validationKey="252B1F96CEF257C94A8829492E6C685AB09E0F817D453F2C6C54EB82F3CEAE83114652334B1E85DD29BB8077C052977C114711EA7775FED06144AFFD44542274" />

 

您将看到,当登录 oa.paioa.com,会同时登录到 MyApp,这是因为是在同一个域名下,并且计算机密钥相同。
同时会登录到 me.paioa.com,这是因为 oa.paioa.com 身份验证 Cookie 的域属性为二级域名 paioa.com,并且有相同的计算机密钥。


 出处:https://www.paioa.com/developer/p/aspnet-auth.htm

「版权声明:本站原创文章,未经授权,不得转载」



首页  -  博客  -  服务条款  -  用户中心  -  联系我们

© PaiOA 2020 派胜科技 保留一切权利。