I learned how to call oauth authorization to get data. This article describes how to enable oauth authorization and control server data access. [Download source code]
First look 1:
There were too many things in the past two days, and the articles were sorted out intermittently.
OK. Proceed to the topic. Here we still need to use the devdefined. oauth framework. It provides basic functions for client access and server token management.
1. oauthchannel
Defines the server user model, oauth interceptor, oauthwebservicehostfactory (inherited from webservicehostfactory, used to add interceptor), and the container and access class (inmemorytokenrepository, inmemorytokenstore) that the requesttoken and accesstoken keep in memory)
Oauthwebservicehostfactory adds an interceptor and uses webservicehost2 (in Microsoft. servicemodel. Web. dll, it is part of the WCF rest starter kit released by Microsoft)
Webservicehost2 overrides the onopening method in servicehost to add an interceptor. Source code of webservicehost2 hits here
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<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; } }}
The Interceptor (oauthinterceptor. CS) converts the requested oauth (in the request header) to 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
First, create a WCF rest service:
Define a basic data model for Sample access:
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"} }; } }}
The data in contacts can be accessed only by the owner's "user". Therefore, the oauthservice implements the following:
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(); } }}
The above name comes from thread. currentprincipal. Identity. Name, that is, the client ID that accesses the current service. This ID is converted from accesstoken (string) to the server user model by the interceptor of the oauth service.
In web. config, using the compatible mechanism of WCF for ASP. NET, form authentication is used to define two users: John and Jane.
<system.web> <compilation debug="true" targetFramework="4.0" /> <authentication mode="Forms"> <forms loginUrl="Pages/Login.aspx" cookieless="UseUri"> <credentials passwordFormat="Clear"> <user name="john" password="password"/> <user name="jane" password="password"/> </credentials> </forms> </authentication> <authorization> <allow users="*"/> </authorization></system.web>
Modify the webservicehostfactory of Global. asax to 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))); }}
As a basic oauth Authorization Service, we also need to provide:
1. Get the requesttoken Service
2. Get the accesstoken Service
Requesttoken. ashx: Return 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: returns the accesstoken for exchanging requesttoken.
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(); } }}
Of course, we also need to provide the user login and authorization pages: Login. aspx and userauthorize. aspx form login will not be detailed, userauthorize. aspx in the way to implement authorization is as follows:
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. ApplicationDefault. aspx initiates a request to obtain the requesttoken. After successful authorization, callback. ashx is called back.
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; } } }}