2015-09-20 11 views
8

मैंने अपने एमवीसी 5 ऐप में लॉगिन प्रदाता के रूप में Google को जोड़ने के लिए this article में निर्देशों का पालन किया है। सभी ठीक काम करते प्रतीत होते हैं, लेकिन जब मैं Google के माध्यम से लॉग इन करता हूं, तो यह चाहता है कि मैं Google द्वारा प्रदान किए गए ईमेल/उपयोगकर्ता नाम को अपने ऐप में एक नए खाते के रूप में पंजीकृत करूं। अगर मैं ईमेल छोड़ता हूं और 'रजिस्टर' बटन पर क्लिक करता हूं, तो यह मुझे बताता है कि पता पहले ही लिया जा चुका है, क्योंकि मैंने पहले अपने ऐप के लॉगिन प्रदाता पर पंजीकरण किया था।किसी मौजूदा खाते के साथ एक नया Google या फेसबुक लॉगिन संबद्ध करें

मैं एमवीसी प्रोजेक्ट टेम्पलेट द्वारा जेनरेट किए गए डिफ़ॉल्ट कोड को कैसे बदल सकता हूं ताकि मुझे Google लॉगिन को मौजूदा स्थानीय खाते से जोड़ सकें?

पीएस मेरे पास फेसबुक के साथ बिल्कुल वही समस्या है।

उत्तर

4

मैं पहचान यह जिस तरह से यह उद्देश्य पर करता है संभालती है, वहाँ ईमेल द्वारा उपयोगकर्ता की पहचान अकेले एक तीसरी पार्टी से आ रही सत्यापित करने के लिए कोई वास्तविक तरीका है के बाद से लगता है। जबकि जोखिम अपेक्षाकृत कम हो सकता है, यह संभव है कि कोई व्यक्ति किसी ऐसे ईमेल पते का उपयोग करके फेसबुक जैसी तीसरी पार्टी के साथ खाता बना सके, जो उसके अंतर्गत नहीं है, और उसके बाद किसी अन्य वेबसाइट पर किसी खाते का प्रतिरूपण करने के लिए उस तृतीय-पक्ष लॉगिन का उपयोग करें एक ही ईमेल से जुड़ा हुआ है।

नतीजतन, पहचान केवल साइन इन करते समय बाहरी लॉगिन के साथ एक नया खाता बनाने देती है, मौजूदा किसी से संलग्न नहीं होती है। हालांकि, उपयोगकर्ता को अन्य माध्यमों द्वारा प्रमाणित करने के बाद, अतिरिक्त लॉगिन को जोड़ने के लिए विधियां प्रदान की जाती हैं।

आप अपेक्षाकृत हल्के सुरक्षा सिर्फ यह सोचते हैं कि यह एक ही व्यक्ति का ईमेल से मेल खाता है तो आप केवल AccountController.cs में ExternalLoginCallback संशोधित आवश्यकता ईमेल द्वारा उपयोगकर्ता को खोजने के लिए प्रयास करने के लिए, के साथ जुड़े जोखिम से चिंतित नहीं कर रहे हैं:

var user = await UserManager.FindByEmailAsync(loginInfo.Email); 

और फिर उन्हें साइन-इन करें:

await SignInManager.SignInAsync(user); 
0

TLDR आप अपने ExternalLoginConfirmation समारोह में मैन्युअल रूप से सभी परिदृश्यों के माध्यम से जाना, और OAuth प्रयोक्ता आईडी के साथ सदस्यता उपयोगकर्ता id से मिलान करने के लिए सक्षम होने के लिए एक डेटाबेस तालिका की आवश्यकता है। इस तरह आप एक से अधिक स्थानीय खाते के साथ कई OAuth खातों को "संबद्ध" कर सकते हैं।

नीचे हमारे परियोजनाओं में से एक से एक कोड का टुकड़ा है - उम्मीद है कि यह काफी स्पष्ट

public ActionResult ExternalLoginCallback() 
{ 
    var returnUrl = HttpContext.Request.QueryString["returnUrl"]; 

    var result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl })); 
    if (result.IsSuccessful == false) 
    { 
     return this.View("ExternalLoginFailure", result); 
    } 

    // Login user if provider represents a valid already registered user 
    if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false)) 
    { 
     return this.RedirectToLocal(returnUrl); 
    } 

    // If the current user is logged in already - add new account 
    if (User.Identity.IsAuthenticated) 
    { 
     OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name); 
     return this.RedirectToLocal(returnUrl); 
    } 

    var membershipUser = Membership.GetUser(result.UserName); 

    // so user is new - then create new membership account 
    if (membershipUser == null) 
    { 
     MembershipCreateStatus createStatus; 
     membershipUser = Membership.CreateUser(username: result.UserName, password: this.GetTempPassword(), email: result.UserName, status: out createStatus); 
     if (createStatus == MembershipCreateStatus.Success) 
     { 
      this.emailService.SendWelcome(this, (Guid)membershipUser.ProviderUserKey); 

      // Associate social network account with created membership account 
      OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, result.UserName); 
      OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false); 

      return this.RedirectToLocal(returnUrl); 
     } 

     // The problem occured while creating membership account 
     this.ViewBag.Error = MembershipErrorNameProvider.FromErrorCode(createStatus); 
     return this.View("CreateMembershipAccountFailure"); 
    } 

    // If membership account already exists -> Associate Social network account with exists membership account 
    OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, result.UserName); 
    OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false); 

    return this.RedirectToLocal(returnUrl); 
} 

और OAuthWebSecurity है है एक सहायक वर्ग है जो सभी प्रदाताओं के साथ सौदों आप समर्थन करते हैं:

public static class OAuthWebSecurity 
{ 
     .... 

    public static bool Login(string providerName, string providerUserId, bool createPersistentCookie) 
    { 
     var context = new HttpContextWrapper(HttpContext.Current); 
     var provider = GetOAuthClient(providerName); 
     var securityManager = new OpenAuthSecurityManager(context, provider, OAuthDataProvider); 
     return securityManager.Login(providerUserId, createPersistentCookie); 
    } 

    public static void CreateOrUpdateAccount(string openAuthProvider, string openAuthId, string userName) 
    { 
     var user = UserRepository.FindByName(userName); 
     if (user == null) 
     { 
      throw new MembershipUserNotFoundException(); 
     } 

     var userOAuthAccount = UserOAuthAccountRepository.Find(openAuthProvider, openAuthId); 
     if (userOAuthAccount == null) 
     { 
      UserOAuthAccountRepository.InsertOrUpdate(new UserOAuthAccount 
      { 
       OAuthProvider = openAuthProvider, 
       OAuthId = openAuthId, 
       UserId = user.Id 
      }); 
     } 
     else 
     { 
      userOAuthAccount.UserId = user.Id; 
     } 

     UserOAuthAccountRepository.Save(); 
    } 
} 
+0

क्या यह बट में दर्द नहीं है कि एमएस ने इतनी सरलता से खेला, मौजूदा उपयोगकर्ताओं का एक छोटा सा उल्लेख भी नहीं? और नए उपयोगकर्ताओं के लिए, जो भी सामान्य विवरण आप सामान्य रूप से एकत्र करेंगे, उसके बजाय एमएस डिफ़ॉल्ट सिर्फ उपयोगकर्ता नाम/ईमेल प्राप्त करता है। इसे नए उपयोगकर्ताओं के लिए 'रजिस्टर' पर रीडायरेक्ट करना चाहिए। – ProfK

+0

अच्छी तरह से, हर किसी का उपयोग मामला अलग है - मुझे लगता है कि उन्होंने एक ढांचा बनाया है जो आप अपेक्षाओं के लिए अपेक्षाकृत आसान कर सकते हैं :) – avs099

1

यह वह जगह है एमवीसी टेम्पलेट में एक सामान्य व्यवहार, चूंकि बाहरी लॉग इन उपयोगकर्ता बनाने का प्रयास करते हैं और यदि उपयोगकर्ता का ईमेल (या बाहरी पहचान) पहले से मौजूद है, तो साइनइन करने का प्रयास करें। इसके अलावा, बाहरी लॉगिन प्रदाता आपके बाहरी पहचान से अलग आपके एप्लिकेशन (स्थानीय रूप से) में एक वैकल्पिक और अद्वितीय पहचानकर्ता असाइन करने का प्रयास करता है। लेकिन, निम्नलिखित अजीब है, जैसा कि आप ने कहा:

अगर मैं ईमेल को वैसे ही छोड़ और 'पंजीकृत करें' बटन क्लिक करें, यह बताता है मुझे उस पते को पहले से ही, के रूप में लिया जाता है कि मैंने पहले पर पंजीकृत है मेरे ऐप का अपना लॉगिन प्रदाता।

कौन सा काम करना चाहिए के बाद से प्रत्येक उपयोगकर्ता के बाह्य id अन्य साइटों में अद्वितीय (मेरा मानना ​​है कि) होना चाहिए जब तक आप तालिका संरचनाओं के बाद से ही पहचान के साथ कई बाहरी खातों पंजीकृत किया है इस तरह दिखता है:

enter image description here

स्तंभ UserId bellow तालिका के UserId स्तंभ के साथ मिलान किया जाएगा:

enter image description here

संदेश शायद ही कभी दिखाया जाएगा, जब कोई उपयोगकर्ता डुप्लिकेट Username असाइन करने का प्रयास करता है जिसे अन्य साइटों में आपके ईमेल या पहचान नाम के साथ समझा जाएगा (उदा। [email protected] SomeNameUsername के रूप में)

+0

यह बाहरी प्रदाता की आईडी नहीं है जो शिकायत करता है डुप्लिकेट है, लेकिन ईमेल जो मैं अपने उपयोगकर्ता नाम के रूप में उपयोग करता हूं। मुझे 1 उपयोगकर्ता नाम और कई बाहरी प्रदाता चाहिए। प्रोजेक्ट टेम्पलेट देता है सेटअप प्रत्येक प्रदाता के लिए एक नया उपयोगकर्ता नाम और प्रदाता आईडी है। – ProfK

+0

@ProfK मेरा अर्थ इस उदाहरण का संदर्भ देता है: मेरे पास दो ईमेल पते हैं जिन्हें [email protected] और [email protected] नाम दिया गया है, तो इस मामले में क्या होगा? –

+0

फिर यदि आपके पास दोनों के लिए स्थानीय खाते हैं, तो किसी के साथ किसी तृतीय पक्ष का उपयोग करने के बाद, आप स्थानीय रूप से भी साइन इन करते हैं और अपने लॉग इन पते के साथ तीसरे पक्ष के टोकन को जोड़ते हैं। – ProfK

-1

यह नीचे दिए गए लिंक की सहायता से आप एक ASP.NET MVC 5 वेब एप्लिकेशन है जो उपभोक्ताओं को किसी बाहरी प्रमाणीकरण प्रदाता से पहचान के साथ OAuth 2.0 का उपयोग करके प्रवेश के लिए सक्षम बनाता का निर्माण करने के लिए किया जाएगा, जैसे कि फेसबुक, ट्विटर, लिंक्डइन, माइक्रोसॉफ्ट, या Google। सादगी के लिए, यह ट्यूटोरियल फेसबुक और Google मौजूदा खातों से प्रमाण-पत्रों के साथ काम करने पर केंद्रित है।

इस संदर्भ लें:

MVC 5 App with Facebook, Twitter, LinkedIn and Google OAuth2 Sign-on (C#)

+1

मेरे पास पहले से ही फेसबुक और Google के माध्यम से लॉग इन हैं, धन्यवाद, लेकिन यह वह नहीं है जो मैं पूछ रहा हूं। यदि आप लिंक किए गए ट्यूटोरियल का पालन करते हैं, तो आप उसी समस्या का अनुभव कर सकते हैं जो मैं वास्तव में पूछ रहा हूं। – ProfK

7

मैं पूरी तरह दूसरा अंक @Chris प्रैट द्वारा उठाए गए लेकिन मैं नहीं यकीन है कि इस्तेमाल किया कोड क्या ओपी पूछा करने के लिए पर्याप्त है हूँ।

ExternalLoginCallback अंदर डिफ़ॉल्ट ब्लॉक में यह कोड जोड़ने का काम

ApplicationUser user = await UserManager.FindByNameAsync(loginInfo.Email); 
if (user != null) 
{ 
    var addLoginResult = await UserManager.AddLoginAsync(user.Id, loginInfo.Login); 
    if (addLoginResult.Succeeded) 
    { 
     await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); 
     return RedirectToLocal(returnUrl); 
    } 
} 
2

यहाँ क्या करना चाहिए कि कैसे मैं इस मुद्दे है कि आप कर रहे हैं हल करने में सक्षम था। यह समाधान आपको अपने ईमेल के साथ साइट पर पंजीकरण करने की अनुमति देगा और यदि आप उसी ईमेल पते से लॉग इन करने के लिए Google का उपयोग करने का प्रयास करेंगे, तो आपको पंजीकरण करने का अनुरोध नहीं किया जाएगा और आप कोई त्रुटि उत्पन्न नहीं करेंगे; अगर आपको स्थानीय रूप से लॉग इन किया गया ईमेल पता आपके Google खाता ईमेल जैसा ही है, तो आपको लॉगिन करने की अनुमति होगी। मैंने डिफ़ॉल्ट बाहरी लॉजिक कॉलबैक कोड संपादित किया है जो वीएस2015 एक if/else कथन के साथ उत्पन्न हुआ है, जो लॉगिन ईमेल से मेल खाने वाले मौजूदा ईमेल की जांच कर रहा है। मुझे उम्मीद है कि इससे आपको अपने प्रश्न के साथ मदद मिलेगी, क्योंकि मेरे पास एक ही समस्या थी और कहीं भी जवाब नहीं मिला। मेरे एकाधिक पोस्ट अनुरोधों को अनदेखा कर दिया गया और शुक्र है, मैंने इस पोस्ट के उत्तरों में से एक को पढ़ा जिसने मुझे अपने स्वयं के समाधान के लिए प्रेरित किया जो वीएस2015 कोर पर मेरे लिए काम कर रहा है।

[HttpGet] 
[AllowAnonymous] 
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null) 
{  

    if (remoteError != null) 
    { 
     ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}"); 
     return View(nameof(Login)); 
    } 
    var info = await _signInManager.GetExternalLoginInfoAsync(); 
    if (info == null) 
    { 
     return RedirectToAction(nameof(Login)); 
    }    

    // Sign in the user with this external login provider if the user already has a login. 
    var email = info.Principal.FindFirstValue(ClaimTypes.Email); 
    var user = await _userManager.FindByNameAsync(email); 
    if (user != null) 
    { 
     await _signInManager.SignInAsync(user, isPersistent: false); 
     return RedirectToLocal(returnUrl); 
    } 
    else 
    { 
     // If user does not already exists, invite User to register. 
     var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false); 
     if (result.Succeeded) 
     { 
      _logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider); 
      return RedirectToLocal(returnUrl); 
     } 

     if (result.RequiresTwoFactor) 
     { 
      return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl }); 
     } 

     if (result.IsLockedOut) 
     { 
      return View("Lockout"); 
     } 
     else 
     { 
      // If the user does not have an account, then ask the user to create an account. 
      ViewData["ReturnUrl"] = returnUrl; 
      ViewData["LoginProvider"] = info.LoginProvider; 
      email = info.Principal.FindFirstValue(ClaimTypes.Email); 
      return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email }); 
     } 
    } 
} 
+2

धन्यवाद। मैंने अपना जवाब संशोधित किया और इसके बजाय समाधान पोस्ट किया। – Johnny

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