zoukankan      html  css  js  c++  java
  • asp.net实现OAuth认证服务端接口

    现在的互联网是开放的互联网,你要想融入这个开放的环境,当然自己也要开放一点。如果你希望别人能够很方便的使用你的网站上的用户及数据,当然要提 供比较开放一点的接口。如果能够实现标准的OAuth认证接口,第三方用户在开发的时候就会容易很多,因为他们很可能在开发微博程序的时候已经做过同样的 事写过很多这样的代码了。

    不过C#实现OAuth认证还真是挺烦的,主要是,类库有好几个,但是,都找不到文档。适用于客户端实现的文档倒是有很多,适用于服务器端的真的没 有。连类库的官方文档都找不到,只有源码里仅存的一份简易Test可以作为参考。费了九牛二虎之力终于算是实现了一个几乎一模一样的OAuth认证接口, 记录一下。

    经过搜索,比较,读资源,读源码,再比较,最后选择了oauth-dot-net这个类库。虽然它已经一年多没更新了,曾经承诺的2.0接口也没有动静,但是,它的Server端实现算是最容易理解和操作的了。

    下载源码也好,Release版本也好,把一堆dll引入到自己的项目中。关于这个项目的类型,直接用VS新建网站即可,不需要web application,也不需要web service,也不需要WCF。但是呢,使用过程中你需要新建几个类,而且这几个类需要在web.config中指定,所以它需要完整的命名空间,简单 起见,新建一个类库,把所有的类定义和通用的方法放到这里面,当然,因为我们的项目原本就有一个用来定义类变量和公共方法的dll,就直接放一起了。

    然后你需要实现几个东西:ConsumerStore,CallbackStore,TokenGenerator,TokenStore,它们分 别实现自己的名字前面加上I的那个接口。具体如何实现以及每个函数的作用,可以参考源码中提供的InMemoryXXX的实现方式。具体来 讲,consumer是一个个应用,或者第三方的接入网站,每个应用有个唯一的appkey和appsecret,跟新浪的应用一样,你需要在这儿实现根 据appkey查找该consumer的功能,每次请求发起,都需要调用。因为创建应用一般来说有自己的流程,所以在这个store可以不用管它。 callback是调用者的返回URL,在申请request_token的时候会传递过来,需要保存下来到用户亲自授权完成以后再读出来进行跳转。 TokenGenerator只有两个函数,用来生成新的request_token和access_token,如何生成它里面的key和 secret,随便你自己,只要永远不重复就可以了,嫌麻烦就直接用GUID。TokenStore是用来查询token的,比如根据tokenkey查 找request_token或者access_token,你可以用自己的数据库来实现,字段也就那几个,也是以后每个请求都要读取的。但是它自己的实 现接口里面忽略了很重要的一点,就是没有把access_token跟用户Id绑定起来,这个一定要自己实现的,不然程序传一个access_token 过来,你找不到是哪个合法用户。

    实现了这几个类以后,在源码里面找到OAuth.Net.Examples.EchoServiceProvider这个示例项目,把它的 web.config里面的oauth.net.serviceprovider和oauth.net.components两段配置信息拷到自己的 web.config里面来,然后修改oauth.net.components这一段里面对应的四个自己已经实现的类,指向自己的类库的位置。

    然后添加一个global.asax,对于网站项目,这个文件是没有codefile文件的,可以直接在asax下面写代码,把示例项目中的那个Init方法复制过来。这时候,基础工作就完成了。

    然后需要实现三个过程,申请request_token(这一步没有界面,对方直接用代码读你的URL获取这个信息),用户跳到authorize 的页面,输入用户名和密码,验证并授权给该客户端,验证完成后返回用户指定的callbackurl,用户再拿该返回链接中的参数申请 access_token(这一步也没有界面,通过程序间完成),保存下你返回的token和secret就可以用在其它所有的读取数据的请求上了。

    示例中已经给你准备好了一个RequestTokenHandler.cs和AccessTokenHandler.cs,不过这两个示例除了把你搞哭没啥大作用。

    新建一个request_token.ashx文件,像RequestTokenHandler.cs一样继承 OAuth.Net.ServiceProvider.RequestTokenHandler这个类,实现里面的IssueRequestToken方 法,这个时候,建议你就不要再参考示例项目里面的这个代码了,而去 OAuth.Net.ServiceProvider.RequestTokenHandler这个类里面,参考它的IssueRequestToken 方法。因为示例项目里面的token和secret都是写死的(包括consumer也是写死的),因此它没有对生成的token做任何保存的动作。实际 上,你需要将这个token保存到数据库里,同时保存callbackurl,至于要调用CallbackStore来保存还是你直接操作自己的数据库字 段,无所谓。这个文件最后是把生成的token和secret以纯文本的形式返回给客户端。

    然后客户端把得到的token字符串作为参数,跳到你的authorize.aspx页面,这里你需要提供用户的登录框,和一个授权按钮。当用户点 下授权按钮的时候,检查用户名密码是否正确,然后根据用户跳转过来的时候传过来的那个oauth_token参数,找到你前面生成的 request_token对应的其它字段(如果你要对request_token设置有效时间,这里需要判断该时间),读出其中的 callbackurl字段,然后,调用 ServiceProviderContext.VerificationProvider.Generate()方法根据该request_token 生成一个oauth_verifier字符串,将该值附加到callbackurl的后面,跳转过去。但是在跳转过去之前,你必须做一件事。

    用户的callbackurl页面收到你的oauth_verifier以后,再连同前面的request_token一起来访问你的 access_token.ashx,申请access_t0ken。所以用户端也必须保存你前面生成的request_token才可以(临时性的,每 次授权前读取,申请到access_token就作废,所以一般用session来保存就行了)。对于access_token.ashx的内容,源码同 样提供了一个例子,不过同样是个一点用都没有的例子,因为它完全没有涉及到授权和生成全局唯一access_token的过程。你可以让你的 access_token的handler继承自OAuth.Net.ServiceProvider.AccessTokenHandler,然后重写 IssueAccessToken方法。这个方法其实很简单,因为父类已经帮你检测了传过来的所有的参数以及签名的正确性,甚至连 access_token和verifier是否匹配都验证过了,所以你要做的就是把对应的access_token返回给用户。你可以生成一个新的 access_token返回给用户,因为它里面包含的token和secret其实就是两个普通的字符串,跟前面用到的所有的变量都没有直接关系,你只 要保存token是唯一的就可以了,因为以后用户做所有的请求,实际都只使用这个token字符串作为自己的唯一身份标志。所以,理所当然,你要把生成的 这个access_token永久性的保存到自己的数据库里,还要把这个token跟进行授权的用户的id关联起来,以便以后每次可以查询到这个用户的身 份,才能传递他的数据回去。

    等等,客户端在申请access_token的时候,只传递了request_token和一个verifier的字符串过来,授权的用户的信息并没有再传回来,你如何知道把哪一个用户关联到这个access_token上?

    所以,你需要把创建新access_token的过程提前,放到authorize的时候,在跳转回callbackurl之前,直接在这里创建一 个新的access_token,将它和你的request_token还有你的用户的信息关联起来,保存到数据库里。然后在用户申请 access_token的时候,你只要根据传递过来的request_token去数据库里找到前面生成的access_token,把两个值返回给客 户端就OK了。

    现在,认证过程已经完成了,用户可以使用你的数据接口了。

    示例中也为你准备了一个echoHandler的测试代码,但是,悲剧的是,这个代码并不包含任何身份验证的过程,是个完全干净的独立的handler,不知道开发团队提供这样一个示例代码的意义何在?

    你可以自己新建一个echoHandler.ashx(或者随便什么名字),你需要以前面的 OAuth.Net.ServiceProvider.AccessTokenHandler作为模板开始你的工作。将它的代码完整的复制到你的 handler文件里面来,慢慢修改。首先,ParseParamters里,检查参数完整性,把VerifierParameter删掉,同样的把 this.CheckVerifier(context, requestContext);也删掉,verifier参数只在申请access_token的时候才会出现。然后把 parameters.AllowOnly检查过程删掉,原因很简单。然后修改SetRequestToken函数,它的代码是通过token参数找到 request_token对象,把它改成通过token参数读取你的数据库里的access_token对象(当然,同时把它关联的用户的信息也读出 来),然后,把IssueAccessToken函数的过程改成你的业务处理过程,比如输出个用户详细信息啥的。至于输出成json还是xml,就看你的 个人喜好和用户的要求了。每个业务处理的handler的返回格式实际是无固定格式的,因为这毕竟是跟你自己的网站业务紧密相关的。

    这个时候,你的网站的标准的RESTful格式的api接口就准备好了,如果用户有开发新浪微博客户端的经验,同样的代码拿过来稍微改改就能完成你 的网站的OAuth认证,然后就可以方便的调用你的其它的数据接口了。(不过新浪现在已经开始推广OAuth2.0接口,而oauth-dot-net类 库目前还没有提供2.0相关的验证方法。如果你有兴趣,可以自己实现一下2.0的交换参数的过程,然后,告诉我一下。

  • 相关阅读:
    zw版【转发·台湾nvp系列Delphi例程】HALCON MoveRectangle
    zw版【转发·台湾nvp系列Delphi例程】HALCON SetIcon1
    zw版【转发·台湾nvp系列Delphi例程】HALCON SetIcon2
    zw版【转发·台湾nvp系列Delphi例程】HALCON DispArc
    zw版【转发·台湾nvp系列Delphi例程】HALCON HSerializedItem
    zw版【转发·台湾nvp系列Delphi例程】HALCON union1
    zw版【转发·台湾nvp系列Delphi例程】HALCON SqrtImage
    zw版【转发·台湾nvp系列Delphi例程】HALCON SubImage
    zw版【转发·台湾nvp系列Delphi例程】HALCON SetWindowExtent
    Raphael绘制圆圈环绕方法
  • 原文地址:https://www.cnblogs.com/shihao/p/2605694.html
Copyright © 2011-2022 走看看