Maison > base de données > tutoriel mysql > le corps du texte

OAuth 学习(2) 自定义OAuth服务端(WCF REST数据访问控制)

WBOY
Libérer: 2016-06-07 15:27:37
original
1308 Les gens l'ont consulté

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

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

OAuth 学习(2)  自定义OAuth服务端(WCF REST数据访问控制)

这两天事太多,文章整理的断断续续OAuth 学习(2)  自定义OAuth服务端(WCF REST数据访问控制)

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

1. OAuthChannel
定义了服务端用户模型,OAuth的拦截器,OAuthWebServiceHostFactory(继承于WebServiceHostFactory,用于添加拦截器),以及 RequestToken 和 AccessToken 保持在内存里的容器及存取类 (InMemoryTokenRepository,InMemoryTokenStore)
OAuth 学习(2)  自定义OAuth服务端(WCF REST数据访问控制)

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

<pre class="brush:php;toolbar:false">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<oauthchannel.models.accesstoken> 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;
        }
    }
}</oauthchannel.models.accesstoken>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

拦截器(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; }
}
Copier après la connexion



2. OAuth WCF Rest Service
首先创建一个 WCF Rest Service:
OAuth 学习(2)  自定义OAuth服务端(WCF REST数据访问控制)
定义一个基础数据模型,供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<contact> Contacts;

        static DataModel()
        {
            Contacts = new List<contact> {
              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"}
            };
        }
    }
}</contact></contact>
Copier après la connexion
Contacts 中的数据只有属于 Owner 的“用户”才可以访问,因此 OAuthService 中实现如下:
namespace OAuthWcfRestService
{
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class OAuthService
    {
        [WebGet(UriTemplate = "Contacts")]
        public List<contact> Contacts()
        {
            var name = Thread.CurrentPrincipal.Identity.Name;
            return DataModel.Contacts.Where(c => c.Owner == name).ToList();
        }        
    }
}</contact>
Copier après la connexion
上面的 name 从 Thread.CurrentPrincipal.Identity.Name 而来,即访问当前服务的客户端ID。这个ID是由OAuth服务的拦截器(Interceptor)实现由 AccessToken(String) 转换成服务端用户模型。

在 web.config 中,利用 WCF 对 ASP.NET 的兼容机制,使用 Form 认证:定义了两个用户:john 和 jane
<system.web>
  <compilation debug="true" targetframework="4.0"></compilation>
  <authentication mode="Forms">
    <forms loginurl="Pages/Login.aspx" cookieless="UseUri">
      <credentials passwordformat="Clear">
        <user name="john" password="password"></user>
        <user name="jane" password="password"></user>
      </credentials>
    </forms>
  </authentication>
  <authorization>
    <allow users="*"></allow>
  </authorization>
</system.web>
Copier après la connexion

并修改 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)));
    }
}
Copier après la connexion

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

<pre class="brush:php;toolbar:false">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();
        }
    }
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
AccessToken.ashx :交换 RequestToken 返回 AccessToken
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

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();
        }
    }
}
Copier après la connexion
当然我们还需要提供用户登录和授权的页面: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);
}
Copier après la connexion

3. 应用

OAuth 学习(2)  自定义OAuth服务端(WCF REST数据访问控制)

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);
        }
    }
}
Copier après la connexion
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; }
        }
    }
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal