您的位置:首页 > 编程语言 > ASP

ASP.NET MVC 3 使用 DotNetOpenAuth 实现SSO

2012-11-08 09:07 253 查看
听到DotNetOpenAuth是去年某一天的事了,当时在读《RESTful Web Service》时突然好像灵光一闪,觉得Authorization这个问题似乎应该在构建服务之前就先考虑清楚,否则服务化似乎就无从谈起了。为什么这么说呢,举例来说,Google Canlendar是一个服务,你现在使用Google Canlendar又构建了另一个服务,并幸运的拥有了一些用户,但这些用户怎么才能放心的把Google的帐户信息交给你,让你拿去Google验证呢;另一点,我们公司现在项目比较多,每个新项目建立后,都要往里复制一份诸如Organization,UserManager之内的公共文件(主要集中在UI层),增加工作量不说,这些不同拷贝的版本更新就是一个严峻的挑战,更不要说如果一个客户同时使用了我们两个产品,就会发现居然同一个人要维护和软件产品数量相同的用户...这一切,使得将Organization之类的组件成为服务的要求变得非常强烈,即把Organization业务本身做为一个应用程序存在,发布在IIS后其他项目使用其提供的数据服务即可,这样就不存在每次都要复制UI,以及多个产品间多套数据的问题了。到这里,使用SSO似乎已经不可避免了,但是有个问题还没有考虑到,在使用Web
Service时不会总是直接使用页面去调用吧,大多数时候得提供一个服务客户端组件,否则有谁会每次调用你一个数据,还在业务层里添加一堆有关Authorization和Cookie的代码?所以看起来使用简单的SSO实现方式,很难高效,体面的解决问题。

于是我就发现居然有DotNetOpenAuth(真不明白为什么被墙了,想看的翻墙吧,源码托管地址)这么个东西了,看介绍似乎就涵盖了我想要的一切功能!

文档可能是最让人又爱又恨的东西了,自已不愿意写文档,但都希望使用别人的东西时有完备的文档。

前两天在学习jqGrid,没有一个像样的文档就灰常痛苦,一天下来,浏览历史里就只有Google的搜索记录了。当时下载DotNetOpenAuth下来也是一样,除了一个API Documents之外,没有任何有点价值的资料,虽然他们提供了好几个样例,但是对于一个比较复杂的技术来说,这些远远不够,最起码得有个Quick Start或是How to吧,可惜官网上几乎啥也没有。也不知到底是啥原因我后来也没有再去看这个组件。

一直到前两天,我还是觉得如果说要考虑无论是Web Service,抑或SOA实践,乃至现在火热的云计算,如果Authorization问题不解决掉,似乎就无从谈起。很多的书上使用大量的篇幅讲解如何设计,实现一个Service,但却很少提及SOA实践或云计算的实务讲解,结果大家一通倒腾之后,一个个所谓的Web Service拔地而起,但怎么看也不像是“云”。解决Authorization问题,还是从DotNetOpenAuth入手比较好,它功能强大,而且oauth和openid是成熟的产品,使用的公司很多,几乎成了事实标准,找一个和当前工作比较贴近的点,就学习下OpenIdSSOProvider吧。

(这篇文章呢,我想来想去不知该如何去写,为什么呢?主要是我认为SOA或是云计算是一个非常飘渺的东西,恶补一段时间后,我总会觉得对其概念还算清楚,但是时间一长就会又模糊不清,写自已都不太清楚的东西,遭人骂是小事,耽误人是大事。我本是个看贴不回贴的人,但是现在网上有关服务设计实务的东西少之有少,DotNetOpenAuth方面的东西也是凤毛麟角,我是不想回贴,但是看贴也没得看,因此权当抛砖引玉,希望能和我有共同想法的人探讨一二)

说了这么多废话后,进入正题...

DotNetOpenAuth本身提供了一SSOProvider示例,但是只有WebForm项目的,没有MVC的SSOProvider示例,本文提供MVC的SSOProvider实现方法,再顺便讲讲个人对于使用DotNetOpenAuth的一点点小体会。

一.SsoOP SSO的服务提供者

1.建立SsoOP项目,我使用了Razor视图引擎,添加DotNetOpenAuth.dll引用。下载地址见上面的源码托管地址.

2.设置web.config文件里面的配置信息,详情请见本文下方示例程序。

3.创建OpenIdController.cs

?
               
{


OpenIdController是SsoRP(SSO消费者)使用OP的入口点,其中Provider是提供登录服务的Action,这点需要在后面提到。

4.创建Xrds.cshtml视图

?
本视图的用法也将在以后提到。

5.创建AskUser.cshtml视图

?
对于本Action的作用,现在还很含糊,只能大概的猜测其意图,其用法也将在以后提到。
6.建立TransferResult类,什么作用呢,这里稍作解释:在ASP.NET WebForm页面中,有人可能用过Server.Transfer方法,该方法MSDN中的解释是:对于当前请求,终止当前页的执行,并使用指向一个新页的指定 URL 路径来开始执行此新页。一般情况下似乎和Redirect方法的作用很像,但是某些特殊场合中,区别是大大的,是什么呢?Redirect是执行客户端重定向,而Transfer是不用客户端重定向的,应该就是HTTP的302状态吧。在使用DotNetOpenAuth的过程中,很多时候也许是基于安全的考虑,OpenId是不允许使用重定向了的请求,不然就会出错。在MVC中有一个RedirectToAction方法很好用,却没有一个TransferToAction方法,甚至没有TransferResult类型,所以不得不自已弄一个。

?
7.其他的代码,限于篇幅,就不一一贴上来了,全放到示例程序里面,结构如下:

/Code/ReadOnlyXmlMembershipProvider.cs    作用:用户验证

/Code/Util.cs    作用:用于处理登录及权限请求,这个类里面的主要方法为:ProcessAuthenticationChallenge,在官方提供的样例中是一个void,用在MVC中,必须使用一个具有ActionResult返回值的方法了。

/AppData/Users.xml    作用:相当于存用户信息的数据库

8.在项目根目录下创建default.aspx,该文件为使用IIS架设程序时的入口

?
OK,SsoOP主要结构就是上面这些,文档结构见下图(其中选中的文件是新增的,其他的都是项目模板自带的):



二.SsoRP 这个RP和人品没有太大关系,作用为SSO的消费者

文档结构如下:



这个项目主要内容如下:

1.将AccountController类中的内容全部注释,添加以下代码:

?
结合SsoOP,将个人的理解稍作解释:

因为在web.config里面使用下面的配置

?
因为使用了Forms模式,在没有登录的情况下,无论访问任何资源,都会使请求转到Account的LogOn Action中,在LogOn中,程序会先向OP的Identifier验证是否存在ProviderEndpoint,OP通过OpenIdController的Xrds Action(既OP节中的Xrds.cshtml视图内容)告诉RP这个提供者是存在并合法的,然后RP向提供者请求认证,反过来,OP倒也要确认RP是否存在并合法(使用RP中的Xrds.cshtml),如果没有问题OP还要验证请求认证的RP是否在白名单中,这个白名单中必须要和returnToBuilder.Path
= "/Account/LogOn";这个值完全一致,比如这里在LogOn后面没有"/"号,那么在白名单中,你就必须使用http://localhost:1220/Account/LogOn,而不能在后面加上“/”号,否则就会不通过。如果一切OK,没有问题页面将转向OP的登录页面,本例中为Account/LogOn,用户输入正确的用户和密码(本例User:bob;Password:test)。



登录完成后,根据LogOn中的代码return RedirectToAction("Identifier", "OpenId");,请求会转向OpenId/Identifier,程序会先去准备响应数据,这些数据中包含了登录用户信息,熟悉openid的人知道,openid总是使用一个url+用户名代表用户名,这个url其实就是另一个发现OP的地方,为什么是另一个?还有一个在哪里呢?就在OpenId/Identifier里面呀,(因为还没有对DotNetOpenAuth深入研究,因此,对于官方示例中“服务发现”这个机制还有点模糊,个人感觉应该就是相当于验证是否相任之类的吧,Identifier应该属于登录前和登录阶段的,当登录完成后使用用户名中地址里面的验证了?),接下来使用ProviderEndpoint.SendResponse();向客户端发送登录结果,并使用return_to里面的信息将请求转到了RP的LogOn中,(在这个过程,RP将使用OP中AskUser“发现”服务提供者。)在LogOn中,根据IAuthenticationResponse的状态信息,确定是登录成功还是登录失败(会携带失败原因信息)来确定请求转向,既然咱都有示例代码了,应该就不会失败吧,所以Home/Index会如期而至。



SsoRP示例有两个,一个是纯MVC模式的,一个是使用MVC + WebForms模式的。

DotNetOpenAuth的资料现在貌似很少,个人对其的研究现在还处于Step by Step的阶段,只能说跟着官方的示例能做出一个MVC实现,但是对于很多具体的原理还是相当不熟悉,这示例只能是解决有和没有的问题,本文中的谬误还望大家不吝赐教,希望有人能发更多有深度的资料。

示例程序
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: