视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
OAuth学习(2)自定义OAuth服务端(WCFREST数据访问控制)
2020-11-09 07:36:02 责编:小采
文档


上篇了解了如何调用 OAuth 授权来获取数据,本篇介绍如何开放OAuth授权,并控制服务端数据访问。[源码下载] 先看一下图: 这两天事太多,文章整理的断断续续 OK,步入正题,这里还是要借力:DevDefined.OAuth 框架。它提供了客户端访问,服务端管理Token的基

上篇了解了如何调用 OAuth 授权来获取数据,本篇介绍如何开放OAuth授权,并控制服务端数据访问。[源码下载]
先看一下图:

这两天事太多,文章整理的断断续续

OK,步入正题,这里还是要借力: DevDefined.OAuth 框架。它提供了客户端访问,服务端管理Token的基础功能。

1. OAuthChannel
定义了服务端用户模型,OAuth的,OAuthWebServiceHostFactory(继承于WebServiceHostFactory,用于添加),以及 RequestToken 和 AccessToken 保持在内存里的容器及存取类 (InMemoryTokenRepository,InMemoryTokenStore)

OAuthWebServiceHostFactory 添加,使用了 WebServiceHost2 (Microsoft.ServiceModel.Web.dll 里,是 Microsoft 发布的WCF REST Starter Kit的一部分)
WebServiceHost2 重写了 ServiceHost 里 OnOpening 方法添加。WebServiceHost2的源代码猛击这里
OAuthWebServiceHostFactory:

using System;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using Microsoft.ServiceModel.Web;
using DevDefined.OAuth.Provider;
using OAuthChannel.Repositories;

namespace OAuthChannel
{
 public class OAuthWebServiceHostFactory : WebServiceHostFactory
 {
 public IOAuthProvider OAuthProvider { get; set; }
 public ITokenRepository AccessTokenRepository { get; set; }

 protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
 {
 var serviceHost = new WebServiceHost2(serviceType, true, baseAddresses);
 var interceptor = new OAuthChannel.OAuthInterceptor(OAuthProvider, AccessTokenRepository);
 serviceHost.Interceptors.Add(interceptor);
 return serviceHost;
 }
 }
}

(OAuthInterceptor.cs)将请求的 OAuth (Request Header中) 转换成 OAuthChannel.Models.AccessToken

public class AccessToken : TokenBase
{
	public string UserName { get; set; }
	public string[] Roles { get; set; }
	public DateTime ExpireyDate { get; set; }
}



2. OAuth WCF Rest Service
首先创建一个 WCF Rest Service:

定义一个基础数据模型,供Sample访问:
namespace OAuthWcfRestService
{
 public class Contact
 {
 public int Id { get; set; }
 public string Name { get; set; }
 public string Email { get; set; }
 public string Owner { get; set; }
 }

 public class DataModel
 {
 public static List Contacts;

 static DataModel()
 {
 Contacts = new List {
 new Contact(){ Id=0, Name="Felix", Email="Felix@test.com", Owner = "jane" },
 new Contact(){ Id=1, Name="Wendy", Email="Wendy@test.com", Owner = "jane"},
 new Contact(){ Id=2, Name="John", Email="John@test.com", Owner = "john"},
 new Contact(){ Id=3, Name="Philip", Email="Philip@mail.com", Owner = "john"}
 };
 }
 }
}
Contacts 中的数据只有属于 Owner 的“用户”才可以访问,因此 OAuthService 中实现如下:
namespace OAuthWcfRestService
{
 [ServiceContract]
 [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
 public class OAuthService
 {
 [WebGet(UriTemplate = "Contacts")]
 public List Contacts()
 {
 var name = Thread.CurrentPrincipal.Identity.Name;
 return DataModel.Contacts.Where(c => c.Owner == name).ToList();
 } 
 }
}
上面的 name 从 Thread.CurrentPrincipal.Identity.Name 而来,即访问当前服务的客户端ID。这个ID是由OAuth服务的(Interceptor)实现由 AccessToken(String) 转换成服务端用户模型。

在 web.config 中,利用 WCF 对 ASP.NET 的兼容机制,使用 Form 认证:定义了两个用户:john 和 jane


 
 
 
 
 
 
 
 
 
 
 
 

并修改 Global.asax 的 WebServiceHostFactory,改为 OAuthWebServiceHostFactory
public class Global : HttpApplication
{
 void Application_Start(object sender, EventArgs e)
 {
 RegisterRoutes();
 }

 private void RegisterRoutes()
 {
 var oauthWebServiceHostFactory = new OAuthChannel.OAuthWebServiceHostFactory 
 { 
 AccessTokenRepository = OAuthServicesLocator.AccessTokenRepository,
 OAuthProvider = OAuthServicesLocator.Provider 
 };
 RouteTable.Routes.Add(new ServiceRoute("OAuthService", oauthWebServiceHostFactory, typeof(OAuthService)));
 }
}

作为一个基本的OAuth授权服务,我们还需要提供:
1. 获取 RequestToken 的服务
2. 获取 AccessToken 的服务
RequestToken.ashx :返回 RequestToken

using System;
using System.Web.UI;
using DevDefined.OAuth.Framework;
using DevDefined.OAuth.Provider;

namespace OAuthWcfRestService
{
 public partial class RequestToken : System.Web.IHttpHandler
 {
 public bool IsReusable
 {
 get { return true; }
 }

 public void ProcessRequest(System.Web.HttpContext context)
 {
 IOAuthContext oauthContext = new OAuthContextBuilder().FromHttpRequest(context.Request);
 IOAuthProvider provider = OAuthManager.Provider;
 IToken token = provider.GrantRequestToken(oauthContext);
 context.Response.Write(token);
 context.Response.End();
 }
 }
}
AccessToken.ashx :交换 RequestToken 返回 AccessToken

using System;
using System.Web.UI;
using DevDefined.OAuth.Framework;
using DevDefined.OAuth.Provider;

namespace OAuthWcfRestService
{
 public partial class AccessToken : System.Web.IHttpHandler
 {
 public bool IsReusable
 {
 get { return true; }
 }

 public void ProcessRequest(System.Web.HttpContext context)
 {
 IOAuthContext oauthContext = new OAuthContextBuilder().FromHttpRequest(context.Request);
 IOAuthProvider provider = OAuthManager.Provider;
 IToken accessToken = provider.ExchangeRequestTokenForAccessToken(oauthContext);
 context.Response.Write(accessToken);
 context.Response.End();
 }
 }
}
当然我们还需要提供用户登录和授权的页面:Login.aspx 和 UserAuthorize.aspx Form登录就不累述了, UserAuthorize.aspx 中实现授权的方法如下:
private void ApproveRequestForAccess(string tokenString)
{ 
 OAuthChannel.Models.RequestToken requestToken = RequestTokenRepository.GetToken(tokenString);
 var accessToken = new OAuthChannel.Models.AccessToken
 {
 ConsumerKey = requestToken.ConsumerKey,
 Realm = requestToken.Realm,
 Token = Guid.NewGuid().ToString(),
 TokenSecret = Guid.NewGuid().ToString(),
 UserName = HttpContext.Current.User.Identity.Name,
 ExpireyDate = DateTime.Now.AddMinutes(1),
 Roles = new string[] { }
 };
 AccessTokenRepository.SaveToken(accessToken);
 requestToken.AccessToken = accessToken;
 RequestTokenRepository.SaveToken(requestToken);
}

3. 应用

Default.aspx 发起请求获取RequestToken,授权成功后回调 Callback.ashx

namespace OAuthConsumerSample
{
 public partial class _Default : Page
 {
 protected void oauthRequest_Click(object sender, EventArgs e)
 {
	 OAuthSession session = OAuthSessionFactory.CreateSession();
 IToken requestToken = session.GetRequestToken();
 if (string.IsNullOrEmpty(requestToken.Token))
 {
 throw new Exception("The request token was null or empty");
 }
 Session[requestToken.Token] = requestToken;
 string callBackUrl = "http://localhost:" + HttpContext.Current.Request.Url.Port + "/Callback.ashx";
 string authorizationUrl = session.GetUserAuthorizationUrlForToken(requestToken, callBackUrl);
 Response.Redirect(authorizationUrl, true);
 }
 }
}
Callback.ashx
namespace OAuthConsumerSample
{
 public partial class Callback : System.Web.IHttpHandler, System.Web.SessionState.IRequiresSessionState
 {
 public void ProcessRequest(System.Web.HttpContext context)
 {
 var session = OAuthSessionFactory.CreateSession();
 string requestTokenString = context.Request["oauth_token"];
 var requestToken = (IToken)context.Session[requestTokenString];
 IToken accessToken = session.ExchangeRequestTokenForAccessToken(requestToken);
 context.Session[requestTokenString] = null;
 context.Session[accessToken.Token] = accessToken;
 context.Response.Redirect("ViewData.ashx?oauth_token=" + accessToken.Token);
 }

 public bool IsReusable
 {
 get { return true; }
 }
 }
}

下载本文
显示全文
专题