<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_晓风</title><subtitle type="text">专注于.NET技术</subtitle><id>http://feed.cnblogs.com/blog/u/11636/rss</id><updated>2011-03-11T04:27:33Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/11636/rss"/><entry><id>http://www.cnblogs.com/Jinglecat/archive/2010/03/14/1685759.html</id><title type="text">实现基于 ASP.NET Forms 身份验证的跨子域单点登录</title><summary type="text">对于跨应用程序的 ASP.NET Forms 身份验证，相信大家应该都不陌生，几年前很多文章都介绍了如何实现，比如 MSDN 的 跨应用程序进行 Forms 身份验证，唐朝程序员 的 ASP.NET站点跨子域名单点登陆（SSO）的实现，dudu 的 关于二级域名Cookie的问题及解决方法。这个方案实际上利用了 cookie 可以跨子域共享，当前几乎所有主流器包括 IE6+/FF3/Opera9/...</summary><published>2010-03-14T13:54:00Z</published><updated>2010-03-14T13:54:00Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Jinglecat/archive/2010/03/14/1685759.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/archive/2010/03/14/1685759.html"/><content type="html">&lt;p&gt;对于跨应用程序的 ASP.NET Forms 身份验证，相信大家应该都不陌生，几年前很多文章都介绍了如何实现，比如 MSDN 的 &lt;a href="http://msdn.microsoft.com/zh-cn/library/eb0zx8fc.aspx"&gt;跨应用程序进行 Forms 身份验证&lt;/a&gt;，&lt;a href="http://www.cnblogs.com/kokoliu/"&gt;唐朝程序员&lt;/a&gt; 的 &lt;a href="http://www.cnblogs.com/kokoliu/archive/2006/08/30/490244.html"&gt;ASP.NET站点跨子域名单点登陆（SSO）的实现&lt;/a&gt;，&lt;a href="http://www.cnblogs.com/dudu/"&gt;dudu&lt;/a&gt; 的 &lt;a href="http://www.cnblogs.com/dudu/archive/2005/07/04/186279.html"&gt;关于二级域名Cookie的问题及解决方法&lt;/a&gt;。这个方案实际上利用了 cookie 可以跨子域共享，当前几乎所有主流器包括 IE6+/FF3/Opera9/Chrome 都支持此特性。但这些文章所介绍的都仅仅是“共享身份票据 cookie ”，而没有“共享登录中心”，也就是说，每个应用程序（站点）都具有自己的 login 实现，只是实现过程确保身份票据 cookie 具有相同的 domain 等属性。如此似乎没有实现完全意义上的 SSO，而且每个站点需要维护自己的登录验证代码，当然对于 &lt;a href="http://msdn.microsoft.com/zh-cn/library/eb0zx8fc.aspx"&gt;跨应用程序进行 Forms 身份验证&lt;/a&gt; 提到的“网络场”这个问题不大，因为这些站点其实都是一份程序的副本而已。那么，假如我们希望实现像 Windows Live 一样只有一个统一的登录验证中心呢？比如我们规划了以下四个个站点：&lt;/p&gt; &lt;table border="1" cellspacing="0" cellpadding="2" width="400"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="200"&gt;&lt;a href="http://www.ssolab01.leoworks.net"&gt;http://www.ssolab01.leoworks.net&lt;/a&gt; &lt;/td&gt; &lt;td valign="top" width="200"&gt;主站站点&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="200"&gt;&lt;a href="http://news.ssolab01.leoworks.net"&gt;http://news.ssolab01.leoworks.net&lt;/a&gt; &lt;/td&gt; &lt;td valign="top" width="200"&gt;新闻频道&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="200"&gt;&lt;a href="http://forum.ssolab01.leoworks.net"&gt;http://forum.ssolab01.leoworks.net&lt;/a&gt; &lt;/td&gt; &lt;td valign="top" width="200"&gt;论坛社区&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="200"&gt;&lt;a href="http://passport.ssolab01.leoworks.net"&gt;http://passport.ssolab01.leoworks.net&lt;/a&gt; &lt;/td&gt; &lt;td valign="top" width="200"&gt;通行证中心&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;其中 &lt;a href="http://passport.ssolab01.leoworks.net"&gt;http://passport.ssolab01.leoworks.net&lt;/a&gt; 作为通行证中心，只在该站点中的 &lt;a href="http://passport.ssolab01.leoworks.net/login.aspx"&gt;http://passport.ssolab01.leoworks.net/login.aspx&lt;/a&gt; 实现登录验证逻辑。假如需要身份验证，其他站点则跳转这个站点进行验证，验证通过之后再跳转到原始请求连接。&lt;/p&gt; &lt;p&gt;大家肯定会觉得很简单，认为只要在子站点中的 web.config 将 forms 元素的 login 设置为 &lt;a href="http://passport.ssolab01.leoworks.net/login.aspx"&gt;http://passport.ssolab01.leoworks.net/login.aspx&lt;/a&gt; 应就可以了，其实不然。没错，如果不用内置缺省 ASP.NET Forms 验证（通过 &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.security.formsauthenticationmodule.aspx"&gt;FormsAuthenticationModule&lt;/a&gt;），就像在 ASP/JSP/PHP 中，完全手动实现，逻辑上很清晰只是代码量问题。但是，一经 &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.security.formsauthenticationmodule.aspx"&gt;FormsAuthenticationModule&lt;/a&gt; 以及实用类 &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.security.formsauthentication.aspx"&gt;FormsAuthentication&lt;/a&gt; 包装与过滤，两个大问题就来了：&lt;/p&gt; &lt;p&gt;1. 支持重定向的 returnUrl 参数包含的是原始请求的相对路径，而不是包含站点主机的完整路径。这在同一个站点内没问题，但是跨站点的时候，登录成功就回不去了。&lt;/p&gt; &lt;p&gt;2. 当手动将 returnUrl 补上完整的主机路径，虽然登录成功，但竟然直接重定向到 &lt;a href="http://passport.ssolab01.leoworks.net"&gt;http://passport.ssolab01.leoworks.net&lt;/a&gt; 。&lt;/p&gt; &lt;p&gt;搜索了半天终于发现解决方案：&lt;/p&gt; &lt;p&gt;对于问题2，比较容易，ASP.NET 2.0 已支持，只要在 forms 元素内设置 enableCrossAppRedirects="true" 。注意这只要在 passport 站点内设置即可，因为 passport 负责跳回原始请求。 &lt;/p&gt; &lt;p&gt;passport&amp;nbsp; 的 web.config&lt;/p&gt;&lt;pre &gt;&lt;authentication mode="Forms"&gt;&#xD;
            &lt;forms enablecrossappredirects="true" loginurl="login.aspx" name="LeoLabSSOFormsAuthPassport" domain="ssolab01.leoworks.net" /&gt;&#xD;
        &lt;/authentication&gt;&#xD;
        &lt;authorization&gt;&#xD;
            &lt;deny users="?" /&gt;&#xD;
            &lt;allow users="*" /&gt;&#xD;
        &lt;/authorization&gt;&#xD;
        &lt;machinekey decryptionkey="7CF2B3F76A9359431E717CA8275EE72EEEDC70ED55152010" validationkey="B3E977D304FB289C182E00C710A099C9F92986DC25AD69F8" validation="SHA1" /&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;www 或 forum 的 web.config&lt;/p&gt;&lt;pre &gt;&lt;authentication mode="Forms"&gt;&#xD;
            &lt;forms loginurl="http://passport.ssolab01.leoworks.net/login.aspx" name="LeoLabSSOFormsAuthPassport" domain="ssolab01.leoworks.net" /&gt;&#xD;
        &lt;/authentication&gt;&#xD;
        &lt;authorization&gt;&#xD;
            &lt;deny users="?" /&gt;&#xD;
            &lt;allow users="*" /&gt;&#xD;
        &lt;/authorization&gt;&#xD;
        &lt;machinekey decryptionkey="7CF2B3F76A9359431E717CA8275EE72EEEDC70ED55152010" validationkey="B3E977D304FB289C182E00C710A099C9F92986DC25AD69F8" validation="SHA1" /&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;对于问题1，需要手动检查用户是否有权限访问目标资源，如果没有重定向到 &lt;a href="http://passport.ssolab01.leoworks.net/login.aspx"&gt;http://passport.ssolab01.leoworks.net/login.aspx&lt;/a&gt; 页面，并带上完整的原始请求地址作为 returnUrl 参数。检查的时机选择在 PostAuthenticateRequest 事件内。检查逻辑可使用 &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.web.security.urlauthorizationmodule.checkurlaccessforprincipal.aspx"&gt;UrlAuthorizationModule.CheckUrlAccessForPrincipal&lt;/a&gt; 方法（注意 ASP.NET 2.0+ 支持）。可以单独写一个 HttpModule 或者直接放入 Global.asax 中。注意这只要在子站点中实现，passport 站点不需要，因为 passport 是站内跳转。 &lt;/p&gt;&lt;pre &gt;&amp;lt;%@ Application Language="C#" %&amp;gt;&#xD;
&#xD;
&lt;/pre&gt;附件是完整的测试示例，注意使用说明： &#xD;
&lt;p&gt;1. 建立 IIS 网站 &lt;/p&gt;&#xD;
&lt;p&gt;在 IIS 中建立三个网站，主机头分别设为： &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.ssolab01.leoworks.net"&gt;http://www.ssolab01.leoworks.net&lt;/a&gt; &lt;br&gt;&lt;a href="http://forum.ssolab01.leoworks.net"&gt;http://forum.ssolab01.leoworks.net&lt;/a&gt; &lt;br&gt;&lt;a href="http://passport.ssolab01.leoworks.net"&gt;http://passport.ssolab01.leoworks.net&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;目录分别指向： &lt;/p&gt;&#xD;
&lt;p&gt;Central &lt;br&gt;Forum &lt;br&gt;Passport &lt;/p&gt;&#xD;
&lt;p&gt;2. 解析 DNS &lt;br&gt;用记事本打开 C:\Windows\System32\drivers\etc\hosts 文件 &lt;/p&gt;&#xD;
&lt;p&gt;添加三条记录 &lt;/p&gt;&#xD;
&lt;p&gt;127.0.0.1&amp;nbsp;&amp;nbsp;&amp;nbsp; passport.ssolab01.leoworks.net &lt;br&gt;127.0.0.1&amp;nbsp;&amp;nbsp;&amp;nbsp; www.ssolab01.leoworks.net &lt;br&gt;127.0.0.1&amp;nbsp;&amp;nbsp;&amp;nbsp; forum.ssolab01.leoworks.net &lt;/p&gt;&#xD;
&lt;p&gt;本机使用 127.0.0.1 即可，若是局域网其他客户端的 hosts 则使用安装以上三网站的主机 IP 地址&lt;/p&gt;&#xD;
&lt;p&gt;下载&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://blogs.leoworks.net/jinglecat/file.axd?file=2010%2f3%2fLeoLab.SSO.FormsAuthCrossSubdomain.zip"&gt;LeoLab.SSO.FormsAuthCrossSubdomain.zip (15.46 kb)&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;原文镜像：&lt;a href="http://blogs.leoworks.net/jinglecat/post/cross-sub-domain-sso-based-forms-auth.aspx"&gt;实现基于 ASP.NET Forms 身份验证的跨子域单点登录&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Jinglecat/aggbug/1685759.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Jinglecat/archive/2010/03/14/1685759.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Jinglecat/archive/2010/01/15/1648233.html</id><title type="text">CSS + jQuery 实现的超 Sexy 下拉菜单</title><summary type="text">早前发现了 Soh Tanaka 分享的非常 Sexy 的 Drop Down Menu w/ jQuery &amp;amp; CSS，稍作修改实现了多级下拉，并实现了 ASP.NET 中通过输出 HTML 动态创建版本，有兴趣的童鞋可以包装成 Server Control。 如何实现Step 1 HTML&amp;lt;ul class="topmenu"&amp;gt; &amp;lt;li&amp;gt;&amp;lt;a href="...</summary><published>2010-01-14T23:30:00Z</published><updated>2010-01-14T23:30:00Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Jinglecat/archive/2010/01/15/1648233.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/archive/2010/01/15/1648233.html"/></entry><entry><id>http://www.cnblogs.com/Jinglecat/archive/2010/01/15/1648216.html</id><title type="text">配置 IIS 7 显示详细错误信息</title><summary type="text">如果你在 IIS 7 中只看到诸如 HTTP Error 500 - Internal Server Error (500 - 内部服务器错误) 的简单错误信息，那么可以通过如下步骤配置 IIS7 以输出详细错误信息。通过 IIS 配置按住 WIN + R 打开命令行输入 inetmgr 打开 IIS 管理  左边目录选择目标站点，在右边 IIS 块中双击 Error Pages  在 Error...</summary><published>2010-01-14T17:29:00Z</published><updated>2010-01-14T17:29:00Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Jinglecat/archive/2010/01/15/1648216.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/archive/2010/01/15/1648216.html"/></entry><entry><id>http://www.cnblogs.com/Jinglecat/archive/2009/09/26/1574687.html</id><title type="text">错误：MMC 不能打开文件</title><summary type="text">在 WIN2K3 R2 标准版 SP2 上安装完 SMTP/POP 服务之后，打开 POP3 Service 服务提示： MMC 不能打开文件 C:\WINDOWS\system32\p3server.msc。这可能是由于文件不存在，不是一个MMC控制台，或者用后来版本的MMC创建 。也可能是由于您没有访问此文件的足够权限”。 MMC cannot open the file C:\WINDOWS...</summary><published>2009-09-26T06:56:00Z</published><updated>2009-09-26T06:56:00Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Jinglecat/archive/2009/09/26/1574687.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/archive/2009/09/26/1574687.html"/></entry><entry><id>http://www.cnblogs.com/Jinglecat/archive/2009/08/28/1555792.html</id><title type="text">TortoiseSVN 不显示图标</title><summary type="text">如果你安装 TortoiseSVN 之后，功能使用正常，但是文件夹或文件左上角就是不显示图标，那么你可能 1. 64bit 系统上装了 32bit 的 TortoiseSVN 解决方法是，再安装 64bit 的 TortoiseSVN，两者可并行运行 2. Windows Explorer Shell 支持的 Overlay Icon 最多 15 个，Windows 自身使用了 4 个，只剩 11...</summary><published>2009-08-28T07:02:00Z</published><updated>2009-08-28T07:02:00Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Jinglecat/archive/2009/08/28/1555792.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/archive/2009/08/28/1555792.html"/></entry><entry><id>http://www.cnblogs.com/Jinglecat/archive/2009/08/26/1554530.html</id><title type="text">关于 VB.NET 中 Obsolete 特性的问题</title><summary type="text">在 Visual Studio 2008 SP1 （包含）之前，如果你编译下面的代码，会得到 BC30668 错误，但同样的代码，VC# 一开始就没有这个问题。我想VC#是合理的，因为在调用堆栈上，如果所有的方法都标识为 Obsolete 也就不算错误了。 &amp;lt;Obsolete("This procedure has been obsoleted", True)&amp;gt; _  Public S...</summary><published>2009-08-26T12:29:00Z</published><updated>2009-08-26T12:29:00Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Jinglecat/archive/2009/08/26/1554530.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/archive/2009/08/26/1554530.html"/></entry><entry><id>http://www.cnblogs.com/Jinglecat/archive/2009/08/24/1553238.html</id><title type="text">Virtual Server 2005 R2 SP1 与 Windows 7 不兼容</title><summary type="text">无法直接在 Windows 7 RTM 64bit 上安装 Virtual Server 2005 R2 SP1 64bit，Windows 服务程序 Virual Server 的执行文件 vssrvc.exe 被系统程序兼容性引擎阻止无法加载安装。即使选择以 Vista 或者 Server 2008 兼容模式运行也无效。google 到一个解决方案是：在组策略中，关闭程序兼容性引擎。WIN+R...</summary><published>2009-08-24T15:15:00Z</published><updated>2009-08-24T15:15:00Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Jinglecat/archive/2009/08/24/1553238.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/archive/2009/08/24/1553238.html"/></entry><entry><id>http://www.cnblogs.com/Jinglecat/archive/2009/06/20/1507482.html</id><title type="text">访问匿名方法块&amp;ldquo;外部&amp;rdquo;变量的需要注意的问题</title><summary type="text">通常情况，下面的匿名方法执行没有问题 // Declare a delegate delegate void Callback(int arg); class TestClass { public static void Main() { int n = 10; Callback c = (m) =&amp;gt; { System.Console.WriteLine("匿名方法块“外部”变量 n is ...</summary><published>2009-06-20T12:49:00Z</published><updated>2009-06-20T12:49:00Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Jinglecat/archive/2009/06/20/1507482.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/archive/2009/06/20/1507482.html"/></entry><entry><id>http://www.cnblogs.com/Jinglecat/archive/2009/04/25/1443547.html</id><title type="text">如何删除 MOSS 共享服务提供程序 (SSP, Shared Service Provider)</title><summary type="text">在 MOSS 2007 管理中心站点找了半天也没有发现一个可以删除 SSP 的入口，难道不能删除？google 到这里 How to delete a default SSP (Shared Service Provider) in MOSS 2007 ，原来MS 又跟我们玩捉迷藏了：既可以用 Central Administration Site 删除，只是这个入口是隐藏的， 也可以使用 sts...</summary><published>2009-04-25T10:34:00Z</published><updated>2009-04-25T10:34:00Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Jinglecat/archive/2009/04/25/1443547.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/archive/2009/04/25/1443547.html"/></entry><entry><id>http://www.cnblogs.com/Jinglecat/archive/2009/04/19/1439210.html</id><title type="text">如何编程动态创建 TreeView (WinForms版)</title><summary type="text">其实动态创建 TreeView/Menu 是再简单不过的一件事了，如果你还记得汉诺塔递归这么一故事，你不应该不知道如何建树，如果你知道MSDN，你也不应该抱怨API不懂得用放在这里仅仅方便初学者参考而已，大虾可略过 ....Web 版本见：ASP.NET DEMO 15: 如何编程动态创建 TreeView[代码]&amp;#160;源码下载&amp;#160;</summary><published>2009-04-19T09:54:00Z</published><updated>2009-04-19T09:54:00Z</updated><author><name>晓风残月</name><uri>http://www.cnblogs.com/Jinglecat/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Jinglecat/archive/2009/04/19/1439210.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Jinglecat/archive/2009/04/19/1439210.html"/></entry></feed>
