您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 其它办公文档 > OAuth2学习及DotNetOpenAuth部分源码研究
在上篇文章中我研究了OpenId及DotNetOpenAuth的相关应用,这一篇继续研究OAuth2.一.什么是OAuth2OAuth是一种开放认证协议,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用.数字2表示现在使用第2代协议.二.OAuth2中的角色OAuth2有四种角色resourceowner资源所有者:比如twitter用户,他在twitter的数据就是资源,他自己就是这些资源的所有者。resourceserver资源服务器:保存资源的服务器,别人要访问受限制的资源就要出示AccessToken(访问令牌)。client客户端:一个经过授权后,可以代表资源所有者访问资源服务器上受限制资源的一方。比如开发者开发的应用。authorizationserver授权服务器:对资源所有者进行认证,认证通过后,向客户端发放AccessToken(访问令牌)。三.认证过程用户访问客户端的网站,想操作自己存放在资源服务提供方的资源。客户端将用户引导至授权服务提供方的授权页面请求用户授权,在这个过程中将客户端的回调连接发送给授权服务提供方。用户在授权服务提供方的网页上输入用户名和密码,然后授权该客户端访问所请求的资源。授权成功后,授权服务提供方对客户端授予一个授权码,网站跳回至客户端。客户端获得授权码后,再次从授权服务提供方请求获取访问令牌。授权服务提供方根据授权码授予客户端访问令牌。客户端使用获取的访问令牌访问存放在资源服务提供方上的受保护的资源。四.获取访问令牌方式从上面可以看到,令牌是串起整个认证流程的核心.OAuth2有四种获取令牌的方式AuthorizationCode授权码方式:这种是推荐使用的,也是最安全的.ImplicitGrant隐式授权:相比授权码授权,隐式授权少了第一步的取AuthorizationCode的过程,而且不会返回refresh_token。主要用于无服务器端的应用,比如浏览器插件。ResourceOwnerPasswordCredentials资源所有者密码证书授权:这种验证主要用于资源所有者对Client有极高的信任度的情况,比如操作系统或高权限程序。只有在不能使用其它授权方式的情况下才使用这种方式。ClientCredentials客户端证书授权:这种情况下Client使用自己的client证书(如client_id及client_secret组成的httpbasic验证码)来获取accesstoken,只能用于信任的client。本文主要讲解第一种获取方式.有能有些人有这样的疑问,为什么授权成功后不直接返回访问令牌,则是获取授权码,然后使用授权码去换访问令牌.这个问题的答案在官方的文档里,原因主要是保障数据安全性.当用户授权成功,浏览器从授权服务器返回客户端时,数据是通过QueryString传递的.如果直接返回访问令牌,则直接在地址栏可见,相关的日志系统也会记录,这会提高令牌被破解的风险.返回授权码,然后客户端通过直接通信使用授权码换取访问令牌,整个过程对用户是不可见的,这样大大提高了安全性.五.DotNetOpenAuth在OAuth2中的应用官方Sample内包含有OAuth的完整示例,其授权服务器使用Mvc编写,客户端与资源服务器使用WebForm编写,数据层使用了EF.为了更加贴进实际使用,减少无关杂音,本人模仿其重写了一个Sample,本文的讲解将围绕自行编写的Sample展开.Sample示例可于文后下载.1.客户端客户端编程主要围绕三个类展开AuthorizationServerDescription,顾名思义,用于对服务端的描述.如下所示privatestaticAuthorizationServerDescriptionAuthServerDescription;privatestaticreadonlyWebServerClientClient;staticOAuth2Client(){AuthServerDescription=newAuthorizationServerDescription();AuthServerDescription.TokenEndpoint=newUri(http://localhost:8301/OAuth/Token);AuthServerDescription.AuthorizationEndpoint=newUri(http://localhost:8301/OAuth/Authorize);Client=newWebServerClient(AuthServerDescription,sampleconsumer,samplesecret);}可以看到,主要设置其两个地址:令牌获取地址与授权地址.然后将其作为参数来构建WebServerClient类.WebServerClient类,是OAuth2的客户端代理类,与授权服务器和资源服务器交互的方法都定义在上面.在实例化时需要传入AuthServerDescription对象,客户端名与客户端密码.这对名称与密码应该是事先向授权服务器申请的,用于标识每一个使用数据的客户端.各个客户端拥有各自的名称与密码.生成客户端代理后,第一件事就是应该访问授权服务器获取授权码.这主要由WebServerClient类的RequestUserAuthorization方法完成.publicvoidRequestUserAuthorization(IEnumerablestringscope=null,UrireturnTo=null);在申请授权码时,还会向授权服务器发送申请权限的范围,参数名叫scope.一般都是一个Url地址.申请成功,授权服务器返回后,客户端需再次访问授权服务器申请访问令牌.这主要由WebServerClient类的ProcessUserAuthorization方法完成publicIAuthorizationStateProcessUserAuthorization(HttpRequestBaserequest=null);成功申请后,会返回一个IAuthorizationState接口对象,其定义如下stringAccessToken{get;set;}DateTime?AccessTokenExpirationUtc{get;set;}DateTime?AccessTokenIssueDateUtc{get;set;}UriCallback{get;set;}stringRefreshToken{get;set;}HashSetstringScope{get;}很好理解,AccessToken为访问令牌,RefreshToken为刷新令牌,AccessTokenIssueDateUtc为访问令牌生成时间,AccessTokenExpirationUtc为访问令牌过期时间,Callback为回调的Url,Scope为权限的范围,或者叫被授权可以访问的地址范围.在Sample中为了简化编程对框架作了二次封装,如下1privatestaticAuthorizationServerDescriptionAuthServerDescription;23privatestaticreadonlyWebServerClientClient;45staticOAuth2Client()6{7AuthServerDescription=newAuthorizationServerDescription();8AuthServerDescription.TokenEndpoint=newUri(http://localhost:8301/OAuth/Token);9AuthServerDescription.AuthorizationEndpoint=newUri(http://localhost:8301/OAuth/Authorize);1011Client=newWebServerClient(AuthServerDescription,sampleconsumer,samplesecret);12}1314privatestaticIAuthorizationStateAuthorization15{16get{return(AuthorizationState)HttpContext.Current.Session[Authorization];}17set{HttpContext.Current.Session[Authorization]=value;}18}1920publicstaticvoidGetUserAuthorization(stringscope)21{22GetUserAuthorization(newstring[]{scope});23}2425publicstaticvoidGetUserAuthorization(IEnumerablestringscopes)26{27if(Authorization!=null)28{29return;30}3132IAuthorizationStateauthorization=Client.ProcessUserAuthorization();33if(authorization==null)34{35Client.RequestUserAuthorization(scopes);3637return;38}3940Authorization=authorization;41HttpContext.Current.Response.Redirect(HttpContext.Current.Request.Path);42}前12行为对象初始化,14到18行将获取的权限对象保存在Session中,属性名为Authorization.客户端使用GetUserAuthorization方法来获取对某地址访问授权.在页面中调用代码如下if(!IsPostBack){OAuth2Client.GetUserAuthorization(http://tempuri.org/IGetData/NameLength);}打开页面,首次调用GetUserAuthorization方法后,首先判断权限对象Authorization是否为空.不为空说明已获取到权限.为空则执行ProcessUserAuthorization方法获取访问令牌,由于此时没有授权码,则返回的权限对象为空.最后通过RequestUserAuthorization方法向授权服务器申请授权码.获取成功后,浏览器页面会刷新,在页面地址后追加了授权码.此时第二次执行GetUserAuthorization方法.权限对象Authorization仍然为空,但由于已有授权码,则ProcessUserAuthorization方法将向授权服务器申请访问令牌.获取成功后将返回的权限对象赋给Authorization属性,然后再次刷新本页面.注意,刷新地址使用的是HttpContext.Current.Request.Path,而此属性是不包括QueryString的.作用是将授权码从地址栏中去除.第三次执行GetUserAuthorization方法,由于权限对象Authorization已不为空,则直接返回.访问令牌默认是有时效的.当过期后,要么走上面三步重新申请一个令牌,不过更好的方法是使用刷新令牌刷新访问令牌.这主要由WebServerClient类的RefreshAuthorization方法完成publicboolRefreshAuthorization(IAuthorizationStateauthorization,TimeSpan?skipIfUsefulLifeExceeds=null);使用访问令牌的方式,是将令牌添加到访问资源服务器Http请求
本文标题:OAuth2学习及DotNetOpenAuth部分源码研究
链接地址:https://www.777doc.com/doc-10861 .html