2015-05-25 11 views
39

मेरा प्रश्न मेरे साथ इतना जटिल है क्योंकि मैं इसे अच्छी तरह से बाहर रखने की कोशिश करता हूं कि मैं किसके साथ संघर्ष कर रहा हूं।वेब और मोबाइल के लिए एएसपी.नेट वेब एपीआई सामाजिक प्रमाणीकरण

लक्ष्य

एक ASP.NET वेबसाइट के उपयोगकर्ताओं के माध्यम से उपयोगकर्ता नाम/पासवर्ड या सामाजिक (फेसबुक, ट्विटर, गूगल, आदि) भी एक एपीआई है कि & साइन-इन रजिस्टर देता है कि लो। इस एपीआई को [Authorize] के साथ लॉक करने की आवश्यकता है। एपीआई को मोबाइल क्लाइंट (एंड्रॉइड, आईओएस, इत्यादि) द्वारा एक्सेस करने में सक्षम होना चाहिए जिसे उपयोगकर्ता नाम/पासवर्ड या सोशल (फेसबुक, ट्विटर, Google, आदि) के माध्यम से साइन इन किया जा सकता है।

पृष्ठभूमि

तो मैंने किया है साइटों के सभी नहीं एक साथ मेरा लक्ष्य से एक या दो कर सकते हैं कि लेकिन। ऑनलाइन उदाहरण हैं और वीएस परियोजनाओं में उदाहरणों में निर्मित हैं जो दिखाते हैं कि कैसे उपयोगकर्ता को सामाजिक ऐप्स के माध्यम से पंजीकरण और साइन-इन करने दें, लेकिन वे केवल वेबसाइट के लिए हैं, न कि मोबाइल के लिए। मैंने एक वेबसाइट बनाई है कि एंड्रॉइड ऐप उस एपीआई के साथ प्रमाणित करने के लिए उपयोगकर्ता नाम/पासवर्ड का उपयोग करता है, लेकिन ओएथ या सोशल क्रेडेंशियल्स के साथ कुछ नहीं।

मैं इस page एक संदर्भ के रूप का उपयोग कर बाहर शुरू कर दिया है, लेकिन मैं कोई सुराग नहीं है कि लेने के लिए और उस में और मेरे मोबाइल एप्लिकेशन प्रवेश के लिए मेरी वेबसाइट प्रवेश के लिए काम करने के लिए कैसे।

This guy यह इतना आसान ध्वनि बनाता है लेकिन इसके लिए कोई कोड नहीं दिखाता है।

प्रश्न

वहाँ एक ट्यूटोरियल या GitHub उदाहरण कहीं है कि मुझे मेरा लक्ष्य को प्राप्त कर सकते हैं है? मैं मूल रूप से ऐसी वेबसाइट चाहता हूं जहां लोग उपयोगकर्ता नाम/पासवर्ड पंजीकृत कर सकें या अपने सोशल अकाउंट का उपयोग कर सकें और उपयोगकर्ता को एक ही डिवाइस (& लॉगिन) को मोबाइल डिवाइस के माध्यम से पंजीकृत करने दें। मोबाइल डिवाइस मूल रूप से डेटा को पुश/पुल करने के लिए एपीआई का उपयोग करेगा, लेकिन मुझे यकीन है कि मेरे एपीआई के साथ सोशल लॉग इन कैसे शामिल किया जाए। मुझे लगता है कि मुझे ओएथ का उपयोग करने और उस मार्ग पर जाने की आवश्यकता है, लेकिन मुझे कोई अच्छा उदाहरण नहीं मिल रहा है जो दिखाता है कि वेब और मोबाइल दोनों के लिए यह कैसे करें।

या शायद सही समाधान यह है कि वेबपृष्ठ सभी कुकी ऑथ हो और एपीआई एक अलग "वेब साइट" हो और सभी टोकन ऑथ हो और वे दोनों एक ही डेटाबेस में बंधे हों?

+0

यदि संभव हो तो आप कामकाजी परियोजना के साथ एक जिथब परियोजना बना सकते हैं। अग्रिम में धन्यवाद। –

उत्तर

27

मैंने एएसपी.NET पहचान का उपयोग करके अपने स्वयं के एएसपी.नेट एमवीसी एप्लिकेशन में सफलतापूर्वक यह कार्य किया है, लेकिन उसके बाद आप जिस मुद्दे का उल्लेख करते हैं उसे दबाएं: मुझे वेब एपीआई का उपयोग करके काम करने की ज़रूरत है ताकि मेरा मोबाइल ऐप भी हो सके मूल रूप से बातचीत करें।

मैं आपके द्वारा लिंक किए गए लेख से अपरिचित था, लेकिन इसके माध्यम से पढ़ने के बाद, मैंने देखा कि बहुत सारे काम और कोड की आवश्यकता नहीं है और कार्यक्षमता जटिल है जो पहले से ही एएसपी.नेट पहचान के भीतर मौजूद है।

यहां मेरी सिफारिशें हैं, और मुझे लगता है कि आप एएसपी.NET पहचान V2 का उपयोग कर रहे हैं जो एमवीसी 5 के आस-पास के पैकेज के बराबर है (नया एमवीसी 6 vNext नहीं)। यह आपकी वेबसाइट और मोबाइल एप्लिकेशन दोनों को एपीआई के माध्यम से स्थानीय लॉगिन (उपयोगकर्ता नाम/पासवर्ड) और बाहरी ओएथ प्रदाता दोनों को आपकी वेबसाइट पर एमवीसी वेब दृश्यों से और आपके मोबाइल एप्लिकेशन से वेब एपीआई कॉल के माध्यम से प्रमाणित करने की अनुमति देगा:

चरण 1. अपनी परियोजना बनाते समय, बीमा करें कि आपके पास एमवीसी और वेब एपीआई दोनों के लिए आवश्यक पैकेज शामिल हैं। एएसपी.नेट परियोजना चयन संवाद में आपके पास चेकबॉक्स का चयन करने का विकल्प होगा, एमवीसी बीमा करें और वेब एपीआई दोनों चेक किए गए हैं।यदि आपने अपनी प्रोजेक्ट बनाई है तो आपने पहले से ऐसा नहीं किया है, तो मैं एक नई प्रोजेक्ट बनाने और खोज के विरुद्ध अपने मौजूदा कोड माइग्रेट करने और निर्भरताओं और टेम्पलेट कोड को मैन्युअल रूप से जोड़ने की सलाह दूंगा।

चरण 2. अपनी स्टार्टअप.एथ.cs फ़ाइल के अंदर, आपको कुकी प्रमाणीकरण का उपयोग करने के लिए ओविन को बताने के लिए कोड की आवश्यकता होगी, कुकीज़ में बाहरी साइन इन करने दें, और ओथ बीयर टोकन का समर्थन करें (इस प्रकार वेब एपीआई कॉल प्रमाणीकृत होंगे)। ये मेरे कार्य परियोजना codebase से प्रासंगिक अंश इस प्रकार हैं:

Startup.Auth.cs

// Enable the application to use a cookie to store information for the signed in user 
     // and to use a cookie to temporarily store information about a user logging in with a third party login provider 
     app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
      LoginPath = new PathString("/account/login"), 
      Provider = new CookieAuthenticationProvider 
      { 
       // Enables the application to validate the security stamp when the user logs in. 
       // This is a security feature which is used when you change a password or add an external login to your account. 
       OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
        validateInterval: TimeSpan.FromMinutes(30), 
        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) 
      } 
     }); 
     app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); 

// Configure the application for OAuth based flow 
     PublicClientId = "self"; 
     OAuthOptions = new OAuthAuthorizationServerOptions 
     { 
      TokenEndpointPath = new PathString("/token"), 
      Provider = new ApplicationOAuthProvider(PublicClientId), 
      AuthorizeEndpointPath = new PathString("/api/account/externallogin"), 
      AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), 
      //AllowInsecureHttp = false 
     }; 

     // Enable the application to use bearer tokens to authenticate users 
     app.UseOAuthBearerTokens(OAuthOptions); 

app.UseTwitterAuthentication(
      consumerKey: "Twitter API Key", 
      consumerSecret: "Twitter API Secret"); 

     app.UseFacebookAuthentication(
      appId: "Facebook AppId", 
      appSecret: "Facebook AppSecret"); 

उपरोक्त कोड में मैं वर्तमान में बाहरी प्रमाणीकरण प्रदाताओं के रूप में ट्विटर और फेसबुक समर्थन करता है; हालांकि, आप app.UserXYZProvider कॉल और अतिरिक्त पुस्तकालयों के साथ अतिरिक्त बाहरी प्रदाताओं को जोड़ सकते हैं और वे यहां प्रदान किए गए कोड के साथ प्लग और प्ले करेंगे।

चरण 3. अपनी WebApiConfig.cs फ़ाइल के अंदर, आपको डिफ़ॉल्ट होस्ट प्रमाणीकरण को दबाए रखने और OAuth bearer टोकन का समर्थन करने के लिए HttpConfiguration को कॉन्फ़िगर करना होगा। व्याख्या करने के लिए, यह आपके आवेदन को एमवीसी और वेब एपीआई के बीच प्रमाणीकरण प्रकारों को अलग करने के लिए बताता है, इस प्रकार आप वेबसाइट के लिए सामान्य कुकी प्रवाह का उपयोग कर सकते हैं, इस बीच आपका आवेदन बिना किसी शिकायत के वेब एपीआई से ओएथ के रूप में वाहक टोकन स्वीकार करेगा या अन्य मुद्दे।

WebApiConfig.cs

// Web API configuration and services 
     // Configure Web API to use only bearer token authentication. 
     config.SuppressDefaultHostAuthentication(); 
     config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 

चरण 4. आप दोनों MVC और वेब एपीआई के लिए एक AccountController (या समतुल्य रूप ठान लिया नियंत्रक) की जरूरत है। मेरी प्रोजेक्ट में मेरे पास दो खाता नियंत्रक फ़ाइलें हैं, बेस नियंत्रक वर्ग से विरासत में एक एमवीसी नियंत्रक, और एक अन्य खाता नियंत्रक एपीकंट्रोलर से विरासत में है जो चीजों को साफ रखने के लिए नियंत्रक.एपीआई नेमस्पेस में है। मैं वेब एपीआई और एमवीसी परियोजनाओं से मानक टेम्पलेट खाता नियंत्रक कोड का उपयोग कर रहा हूं।

AccountController.cs (Controllers.API नाम स्थान)

using System; 
using System.Collections.Generic; 
using System.Net.Http; 
using System.Security.Claims; 
using System.Security.Cryptography; 
using System.Threading.Tasks; 
using System.Web; 
using System.Web.Http; 
using System.Web.Http.ModelBinding; 
using Microsoft.AspNet.Identity; 
using Microsoft.AspNet.Identity.Owin; 
using Microsoft.Owin.Security; 
using Microsoft.Owin.Security.Cookies; 
using Microsoft.Owin.Security.OAuth; 

using Disco.Models.API; 
using Disco.Providers; 
using Disco.Results; 

using Schloss.AspNet.Identity.Neo4j; 
using Disco.Results.API; 

namespace Disco.Controllers.API 
{ 
    [Authorize] 
    [RoutePrefix("api/account")] 
    public class AccountController : ApiController 
    { 
     private const string LocalLoginProvider = "Local"; 
     private ApplicationUserManager _userManager; 

     public AccountController() 
     {    
     } 

     public AccountController(ApplicationUserManager userManager, 
      ISecureDataFormat<AuthenticationTicket> accessTokenFormat) 
     { 
      UserManager = userManager; 
      AccessTokenFormat = accessTokenFormat; 
     } 

     public ApplicationUserManager UserManager 
     { 
      get 
      { 
       return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>(); 
      } 
      private set 
      { 
       _userManager = value; 
      } 
     } 

     public ISecureDataFormat<AuthenticationTicket> AccessTokenFormat { get; private set; } 

     // GET account/UserInfo 
     [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)] 
     [Route("userinfo")] 
     public UserInfoViewModel GetUserInfo() 
     { 
      ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity); 

      return new UserInfoViewModel 
      { 
       Email = User.Identity.GetUserName(), 
       HasRegistered = externalLogin == null, 
       LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null 
      }; 
     } 

     // POST account/Logout 
     [Route("logout")] 
     public IHttpActionResult Logout() 
     { 
      Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType); 
      return Ok(); 
     } 

     // GET account/ManageInfo?returnUrl=%2F&generateState=true 
     [Route("manageinfo")] 
     public async Task<ManageInfoViewModel> GetManageInfo(string returnUrl, bool generateState = false) 
     { 
      IdentityUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); 

      if (user == null) 
      { 
       return null; 
      } 

      List<UserLoginInfoViewModel> logins = new List<UserLoginInfoViewModel>(); 

      foreach (UserLoginInfo linkedAccount in await UserManager.GetLoginsAsync(User.Identity.GetUserId())) 
      { 
       logins.Add(new UserLoginInfoViewModel 
       { 
        LoginProvider = linkedAccount.LoginProvider, 
        ProviderKey = linkedAccount.ProviderKey 
       }); 
      } 

      if (user.PasswordHash != null) 
      { 
       logins.Add(new UserLoginInfoViewModel 
       { 
        LoginProvider = LocalLoginProvider, 
        ProviderKey = user.UserName, 
       }); 
      } 

      return new ManageInfoViewModel 
      { 
       LocalLoginProvider = LocalLoginProvider, 
       Email = user.UserName, 
       Logins = logins, 
       ExternalLoginProviders = GetExternalLogins(returnUrl, generateState) 
      }; 
     } 

     // POST account/ChangePassword 
     [Route("changepassword")] 
     public async Task<IHttpActionResult> ChangePassword(ChangePasswordBindingModel model) 
     { 
      if (!ModelState.IsValid) 
      { 
       return BadRequest(ModelState); 
      } 

      IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, 
       model.NewPassword); 

      if (!result.Succeeded) 
      { 
       return GetErrorResult(result); 
      } 

      return Ok(); 
     } 

     // POST account/SetPassword 
     [Route("setpassword")] 
     public async Task<IHttpActionResult> SetPassword(SetPasswordBindingModel model) 
     { 
      if (!ModelState.IsValid) 
      { 
       return BadRequest(ModelState); 
      } 

      IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword); 

      if (!result.Succeeded) 
      { 
       return GetErrorResult(result); 
      } 

      return Ok(); 
     } 

     // POST account/AddExternalLogin 
     [Route("addexternallogin")] 
     public async Task<IHttpActionResult> AddExternalLogin(AddExternalLoginBindingModel model) 
     { 
      if (!ModelState.IsValid) 
      { 
       return BadRequest(ModelState); 
      } 

      Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie); 

      AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken); 

      if (ticket == null || ticket.Identity == null || (ticket.Properties != null 
       && ticket.Properties.ExpiresUtc.HasValue 
       && ticket.Properties.ExpiresUtc.Value < DateTimeOffset.UtcNow)) 
      { 
       return BadRequest("External login failure."); 
      } 

      ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity); 

      if (externalData == null) 
      { 
       return BadRequest("The external login is already associated with an account."); 
      } 

      IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), 
       new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey)); 

      if (!result.Succeeded) 
      { 
       return GetErrorResult(result); 
      } 

      return Ok(); 
     } 

     // POST account/RemoveLogin 
     [Route("removelogin")] 
     public async Task<IHttpActionResult> RemoveLogin(RemoveLoginBindingModel model) 
     { 
      if (!ModelState.IsValid) 
      { 
       return BadRequest(ModelState); 
      } 

      IdentityResult result; 

      if (model.LoginProvider == LocalLoginProvider) 
      { 
       result = await UserManager.RemovePasswordAsync(User.Identity.GetUserId()); 
      } 
      else 
      { 
       result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), 
        new UserLoginInfo(model.LoginProvider, model.ProviderKey)); 
      } 

      if (!result.Succeeded) 
      { 
       return GetErrorResult(result); 
      } 

      return Ok(); 
     } 

     // GET account/ExternalLogin 
     [OverrideAuthentication] 
     [HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)] 
     [AllowAnonymous] 
     [Route("externallogin", Name = "ExternalLoginAPI")] 
     public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null) 
     { 
      if (error != null) 
      { 
       return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error)); 
      } 

      if (!User.Identity.IsAuthenticated) 
      { 
       return new ChallengeResult(provider, this); 
      } 

      ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity); 

      if (externalLogin == null) 
      { 
       return InternalServerError(); 
      } 

      if (externalLogin.LoginProvider != provider) 
      { 
       Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie); 
       return new ChallengeResult(provider, this); 
      } 

      ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider, 
       externalLogin.ProviderKey)); 

      bool hasRegistered = user != null; 

      if (hasRegistered) 
      { 
       Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie); 

       ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager, 
        OAuthDefaults.AuthenticationType); 
       ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager, 
        CookieAuthenticationDefaults.AuthenticationType); 

       AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName); 
       Authentication.SignIn(properties, oAuthIdentity, cookieIdentity); 
      } 
      else 
      { 
       IEnumerable<Claim> claims = externalLogin.GetClaims(); 
       ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType); 
       Authentication.SignIn(identity); 
      } 

      return Ok(); 
     } 

     // GET account/ExternalLogins?returnUrl=%2F&generateState=true 
     [AllowAnonymous] 
     [Route("externallogins")] 
     public IEnumerable<ExternalLoginViewModel> GetExternalLogins(string returnUrl, bool generateState = false) 
     { 
      IEnumerable<AuthenticationDescription> descriptions = Authentication.GetExternalAuthenticationTypes(); 
      List<ExternalLoginViewModel> logins = new List<ExternalLoginViewModel>(); 

      string state; 

      if (generateState) 
      { 
       const int strengthInBits = 256; 
       state = RandomOAuthStateGenerator.Generate(strengthInBits); 
      } 
      else 
      { 
       state = null; 
      } 

      foreach (AuthenticationDescription description in descriptions) 
      { 
       ExternalLoginViewModel login = new ExternalLoginViewModel 
       { 
        Name = description.Caption, 
        Url = Url.Route("ExternalLogin", new 
        { 
         provider = description.AuthenticationType, 
         response_type = "token", 
         client_id = Startup.PublicClientId, 
         redirect_uri = new Uri(Request.RequestUri, returnUrl).AbsoluteUri, 
         state = state 
        }), 
        State = state 
       }; 
       logins.Add(login); 
      } 

      return logins; 
     } 

     // POST account/Register 
     [AllowAnonymous] 
     [Route("register")] 
     public async Task<IHttpActionResult> Register(RegisterBindingModel model) 
     { 
      if (!ModelState.IsValid) 
      { 
       return BadRequest(ModelState); 
      } 

      var user = new ApplicationUser() { UserName = model.Email, Email = model.Email }; 

      IdentityResult result = await UserManager.CreateAsync(user, model.Password); 

      if (!result.Succeeded) 
      { 
       return GetErrorResult(result); 
      } 

      return Ok(); 
     } 

     // POST account/RegisterExternal 
     [OverrideAuthentication] 
     [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)] 
     [Route("registerexternal")] 
     public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model) 
     { 
      if (!ModelState.IsValid) 
      { 
       return BadRequest(ModelState); 
      } 

      var info = await Authentication.GetExternalLoginInfoAsync(); 
      if (info == null) 
      { 
       return InternalServerError(); 
      } 

      var user = new ApplicationUser() { UserName = model.Email, Email = model.Email }; 

      IdentityResult result = await UserManager.CreateAsync(user); 
      if (!result.Succeeded) 
      { 
       return GetErrorResult(result); 
      } 

      result = await UserManager.AddLoginAsync(user.Id, info.Login); 
      if (!result.Succeeded) 
      { 
       return GetErrorResult(result); 
      } 
      return Ok(); 
     } 

     protected override void Dispose(bool disposing) 
     { 
      if (disposing && _userManager != null) 
      { 
       _userManager.Dispose(); 
       _userManager = null; 
      } 

      base.Dispose(disposing); 
     } 

     #region Helpers 

     private IAuthenticationManager Authentication 
     { 
      get { return Request.GetOwinContext().Authentication; } 
     } 

     private IHttpActionResult GetErrorResult(IdentityResult result) 
     { 
      if (result == null) 
      { 
       return InternalServerError(); 
      } 

      if (!result.Succeeded) 
      { 
       if (result.Errors != null) 
       { 
        foreach (string error in result.Errors) 
        { 
         ModelState.AddModelError("", error); 
        } 
       } 

       if (ModelState.IsValid) 
       { 
        // No ModelState errors are available to send, so just return an empty BadRequest. 
        return BadRequest(); 
       } 

       return BadRequest(ModelState); 
      } 

      return null; 
     } 

     private class ExternalLoginData 
     { 
      public string LoginProvider { get; set; } 
      public string ProviderKey { get; set; } 
      public string UserName { get; set; } 

      public IList<Claim> GetClaims() 
      { 
       IList<Claim> claims = new List<Claim>(); 
       claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider)); 

       if (UserName != null) 
       { 
        claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider)); 
       } 

       return claims; 
      } 

      public static ExternalLoginData FromIdentity(ClaimsIdentity identity) 
      { 
       if (identity == null) 
       { 
        return null; 
       } 

       Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier); 

       if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer) 
        || String.IsNullOrEmpty(providerKeyClaim.Value)) 
       { 
        return null; 
       } 

       if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer) 
       { 
        return null; 
       } 

       return new ExternalLoginData 
       { 
        LoginProvider = providerKeyClaim.Issuer, 
        ProviderKey = providerKeyClaim.Value, 
        UserName = identity.FindFirstValue(ClaimTypes.Name) 
       }; 
      } 
     } 

     private static class RandomOAuthStateGenerator 
     { 
      private static RandomNumberGenerator _random = new RNGCryptoServiceProvider(); 

      public static string Generate(int strengthInBits) 
      { 
       const int bitsPerByte = 8; 

       if (strengthInBits % bitsPerByte != 0) 
       { 
        throw new ArgumentException("strengthInBits must be evenly divisible by 8.", "strengthInBits"); 
       } 

       int strengthInBytes = strengthInBits/bitsPerByte; 

       byte[] data = new byte[strengthInBytes]; 
       _random.GetBytes(data); 
       return HttpServerUtility.UrlTokenEncode(data); 
      } 
     } 

     #endregion 
    } 
} 

चरण 5. तुम भी सर्वर पैदा करते हैं और मान्य कर सकते हैं तो OAuth एक ApplicationOAuthProvider बनाने की जरूरत: यहाँ खाता नियंत्रक के एपीआई संस्करण है टोकन। यह वेबएपीआई नमूना परियोजना में प्रदान किया जाता है। इस फ़ाइल की मेरी संस्करण है:

ApplicationOAuthProvider.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Security.Claims; 
using System.Threading.Tasks; 
using Microsoft.AspNet.Identity; 
using Microsoft.AspNet.Identity.Owin; 
using Microsoft.Owin.Security; 
using Microsoft.Owin.Security.Cookies; 
using Microsoft.Owin.Security.OAuth; 
using Butler.Models; 

using Schloss.AspNet.Identity.Neo4j; 

namespace Butler.Providers 
{ 
    public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider 
    { 
     private readonly string _publicClientId; 

     public ApplicationOAuthProvider(string publicClientId) 
     { 
      if (publicClientId == null) 
      { 
       throw new ArgumentNullException("publicClientId"); 
      } 

      _publicClientId = publicClientId; 
     } 

     public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
     { 
      var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>(); 

      ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password); 

      if (user == null) 
      { 
       context.SetError("invalid_grant", "The user name or password is incorrect."); 
       return; 
      } 

      ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, 
       OAuthDefaults.AuthenticationType); 
      ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager, 
       CookieAuthenticationDefaults.AuthenticationType); 

      AuthenticationProperties properties = CreateProperties(user.UserName); 
      AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties); 
      context.Validated(ticket); 
      context.Request.Context.Authentication.SignIn(cookiesIdentity); 
     } 

     public override Task TokenEndpoint(OAuthTokenEndpointContext context) 
     { 
      foreach (KeyValuePair<string, string> property in context.Properties.Dictionary) 
      { 
       context.AdditionalResponseParameters.Add(property.Key, property.Value); 
      } 

      return Task.FromResult<object>(null); 
     } 

     public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
     { 
      // Resource owner password credentials does not provide a client ID. 
      if (context.ClientId == null) 
      { 
       context.Validated(); 
      } 

      return Task.FromResult<object>(null); 
     } 

     public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context) 
     { 
      if (context.ClientId == _publicClientId) 
      { 
       //Uri expectedRootUri = new Uri(context.Request.Uri, "/"); 

       //if (expectedRootUri.AbsoluteUri == context.RedirectUri) 
       //{ 
        context.Validated(); 
       //} 
      } 

      return Task.FromResult<object>(null); 
     } 

     public static AuthenticationProperties CreateProperties(string userName) 
     { 
      IDictionary<string, string> data = new Dictionary<string, string> 
      { 
       { "userName", userName } 
      }; 
      return new AuthenticationProperties(data); 
     } 
    } 
} 

भी शामिल ChallengeResult है, जो अपने आवेदन के जाल एपीआई हाथ करने के लिए बाहरी लॉगिन प्रदाताओं द्वारा प्रदान की चुनौतियों को संभालने के लिए प्रयोग करेंगे अपने उपयोगकर्ता को प्रमाणित:

ChallengeResult.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net; 
using System.Net.Http; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Web.Http; 

namespace Butler.Results 
{ 
    public class ChallengeResult : IHttpActionResult 
    { 
     public ChallengeResult(string loginProvider, ApiController controller) 
     { 
      LoginProvider = loginProvider; 
      Request = controller.Request; 
     } 

     public string LoginProvider { get; set; } 
     public HttpRequestMessage Request { get; set; } 

     public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
     { 
      Request.GetOwinContext().Authentication.Challenge(LoginProvider); 

      HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized); 
      response.RequestMessage = Request; 
      return Task.FromResult(response); 
     } 
    } 
} 

कोड के उस सेट के साथ, आप उपयोगकर्ता को पंजीकृत करने के लिए खाता नियंत्रक के एपीआई संस्करण पर HTTP GET और HTTP पोस्ट करने में सक्षम होंगे, उपयोगकर्ता नाम और पासवर्ड का उपयोग करके बेयरर टोकन प्राप्त करने के लिए लॉगिन करें, बाहरी लॉग इन जोड़ें/हटाएं, प्रबंधित करें बाहरी लॉग इन, और सबसे महत्वपूर्ण रूप से आपकी समस्या के लिए, आपके आवेदन के लिए ओएथ बेयरर टोकन के बदले में बाहरी लॉगिन टोकन में गुजरकर प्रमाणित करें।

+0

मुझे उम्मीद है कि यह मदद करता है, और यदि आवश्यक हो तो स्पष्टता या वैकल्पिक तरीकों के साथ मदद के लिए मैं इस उत्तर को अद्यतन और सुधारना जारी रखूंगा। डिस्को/बटलर अलग-अलग नामस्थानों के साथ एक ही प्रोजेक्ट हैं, मैं भ्रम के लिए क्षमा चाहता हूं। साथ ही, विभिन्न फाइलों में शामिल श्लॉस लाइब्रेरी इसलिए है क्योंकि एएसपी.नेट पहचान के लिए मेरा एप्लीकेशन यूज़र और उपयोगकर्तास्टोर नियो 4j का उपयोग करता है और एंटीटी फ्रेमवर्क नहीं करता है। फाइलों में कोड पर इसका बिल्कुल असर नहीं पड़ता है, और इन फ़ाइलों में कोड को किसी भी ओविन/एएसपी.NET एप्लिकेशन के साथ प्लग और प्ले करना चाहिए जब तक कि आपके पास आपकी परियोजना में एमवीसी और वेब एपीआई निर्भरताएं हों। –

+0

वाह यह आश्चर्यजनक है! मैं अपने वर्तमान प्रोजेक्ट में जो कुछ भी रखता हूं उसके साथ बहुत सारी समानताएं देखता हूं। मुझे जल्द ही कुछ समय मिलेगा और आपके उदाहरणों को आजमाएं और देखें कि क्या मैं इसे काम पर ला सकता हूं। मैं अपने निष्कर्षों की रिपोर्ट करूंगा! – Travyguy9

+0

हां, भालू टोकन जवाब हैं। अब क्लाइंट ऐप में यह भालू टोकन है और इसमें प्रत्येक अनुरोध के शीर्षलेख में शामिल है। अच्छा जवाब दिया। –

2

मैं कहना है हाँ आप दो अलग-अलग एक ही डाटाबेस से बंधा परियोजनाओं हो सकता है और सिर्फ MVC/वेब है कि आपके प्रश्न के दूसरे भाग के लिए एक अलग जवाब के रूप में यह द्वारा जोड़ा जा रहा फॉर्म्स वेबसाइट परियोजना उपयोग सभी कुकी प्रमाणीकरण और उसके बाद एक अलग वेब एपीआई प्रोजेक्ट है जो सभी टोकन प्रमाणीकरण है।

स्रोत कोड उदाहरणों के साथ मेरे लंबे उत्तर में मैंने जो मूल रूप से किया है, वह दो अलग-अलग परियोजनाओं को एक परियोजना में जोड़ती है ताकि अनावश्यक मॉडल कोड और नियंत्रक कोड से बच सकें। मेरे मामले में यह मेरे लिए और अधिक समझ में आया; हालांकि, मैं यह कहने के इच्छुक हूं कि यह व्यक्तिगत प्राथमिकता और आपकी परियोजना की जरूरतों को निर्धारित करने के लिए है कि दो अलग-अलग परियोजनाओं, एक वेबसाइट और एक वेब एपीआई एंडपॉइंट को बनाए रखना है या उन्हें गठबंधन करना है।

एएसपी.नेट को बहुत लचीला और प्लग और मिडलवेयर के रूप में खेलने के लिए डिज़ाइन किया गया था और मैं यह प्रमाणित कर सकता हूं कि मेरी परियोजना मौजूद है और दो अलग-अलग परियोजनाओं में कोड के साथ बिल्कुल काम करती है और अब एक संयुक्त परियोजना के रूप में।

+0

धन्यवाद। मुझे पता चला कि आप यह कर सकते हैं। मैं इसके प्रशंसक नहीं हूं लेकिन सोचा कि मैं इस मार्ग पर जाऊंगा क्योंकि मैं इसे दोनों के लिए काम नहीं कर सका। मैं उपरोक्त आपका उदाहरण देखता हूं जो इसे एक साइट के रूप में करता है और इसका परीक्षण करेगा और मेरे निष्कर्षों की रिपोर्ट करेगा। एक बार फिर धन्यवाद! – Travyguy9

+1

भविष्य में, दूसरा जवाब न जोड़ें जब तक कि यह एक अलग उत्तर न हो। कृपया दोनों उत्तरों को गठबंधन करें। मैं समझता हूं कि उत्तर बहुत बड़ा हो जाता है, लेकिन उत्तरों का उपयोग खंड नहीं है। कृपया दोनों उत्तरों को गठबंधन करें और इसे हटा दें। –

+0

मैंने माना कि एक परियोजना बनाम एक परियोजना वास्तव में अलग है लेकिन मैं आपकी तर्क समझता हूं। –

3

आप को देखने के लिए लेख की इस श्रृंखला पर एक नजर है करने के लिए चाहते हो सकता है कि क्या यह अपने लक्ष्य को शामिल किया गया: Taiseer Joudeh

लेख (जो भी अक्सर इतने पर सवालों के जवाब) द्वारा

Token Based Authentication using ASP.NET Web API 2, Owin, and Identity OWIN का उपयोग करके टोकन आधारित प्रमाणीकरण सेवा बनाने और बाहरी लॉग इन (जैसे फेसबुक और Google+) का उपयोग करके भागों में से एक को कवर करने के बारे में हैं। उदाहरण मुख्य रूप से वेब सेवा के उपभोक्ता के रूप में वेब एप्लिकेशन के आसपास केंद्रित होते हैं, लेकिन इसे मोबाइल एप्लिकेशन पर भी काम करना चाहिए। लेखों में एक गिटहब परियोजना है और एक बहुत सक्रिय टिप्पणी अनुभाग है, जहां शायद ही कोई प्रश्न अनुत्तरित हो जाता है।

आशा है कि यह आपको अपने लक्ष्य तक ले जायेगा।

संबंधित मुद्दे