ASP.NET कोर पहचान - वर्तमान उपयोगकर्ता प्राप्त करें


84

MVC5 में वर्तमान में लॉग इन करने के लिए, हमें बस इतना करना था:

using Microsoft.AspNet.Identity;
[Authorize]
public IHttpActionResult DoSomething() {
    string currentUserId = User.Identity.GetUserId();
}

अब, ASP.NET कोर के साथ मैंने सोचा कि यह काम करना चाहिए, लेकिन यह एक त्रुटि फेंकता है।

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Http;

private readonly UserManager<ApplicationUser> _userManager;
[HttpPost]
[Authorize]
public async Task<IActionResult> StartSession() {
    var curUser = await _userManager.GetUserAsync(HttpContext.User);
}

कोई विचार?

EDIT: गेरार्डो की प्रतिक्रिया पटरी पर है, लेकिन उपयोगकर्ता की वास्तविक "आईडी" प्राप्त करने के लिए, यह काम करने लगता है:

ClaimsPrincipal currentUser = this.User;
var currentUserID = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;

आपका सवाल क्या है?
गेरार्डो ग्रिग्नोली

आपको केवल आईडी की आवश्यकता है? मैंने अपने उत्तर को जोड़ने के लिए इसे और अधिक फैंसी _userManager.GetUserId (उपयोगकर्ता) का उपयोग करके कैसे प्राप्त किया
Gerardo Grignoli

हां, मुख्य रूप से मुझे AspNetUsers तालिका से या सत्र से आईडी की आवश्यकता है। currentUser.FindFirst (ClaimTypes.NameIdentifier) ​​।वायु दावों का उपयोग करके आईडी देता है। यह UserManager के साथ भी काम करता है! धन्यवाद जेरार्डो! क्या एक तरीका दूसरे की तुलना में अधिक कुशल है?
22

UserManager आंतरिक रूप से करता है। .FindFirst (ClaimTypes.NameIdentifier)। तो यह एक ही प्रदर्शन-वार है। मुझे पढ़ने में आसानी के लिए सूदखोर एनकैप्सुलेशन पसंद है। दूसरी तरफ .GetUserAsync()धीमी है क्योंकि यह डीबी तक जाती है।
गेरार्डो ग्रिग्नोली

मैं पूरी तरह से गेरार्डो से सहमत हूं। धन्यवाद !
जुबुन

जवाबों:


145

मान लें कि आपका कोड MVC कंट्रोलर के अंदर है:

public class MyController : Microsoft.AspNetCore.Mvc.Controller

से Controllerआधार वर्ग, आप प्राप्त कर सकते हैं IClaimsPrincipalसे Userसंपत्ति

System.Security.Claims.ClaimsPrincipal currentUser = this.User;

आप सीधे दावों की जांच कर सकते हैं (डेटाबेस के लिए एक गोल यात्रा के बिना):

bool IsAdmin = currentUser.IsInRole("Admin");
var id = _userManager.GetUserId(User); // Get user id:

अन्य क्षेत्रों को डेटाबेस की उपयोगकर्ता इकाई से प्राप्त किया जा सकता है:

  1. निर्भरता इंजेक्शन का उपयोग करके उपयोगकर्ता प्रबंधक प्राप्त करें

    private UserManager<ApplicationUser> _userManager;
    
    //class constructor
    public MyController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }
    
  2. और इसका उपयोग करें:

    var user = await _userManager.GetUserAsync(User);
    var email = user.Email;
    

6
और अगर मैं एक सेवा वर्ग में हूँ और नियंत्रक में नहीं, जहाँ मेरे पास उपयोगकर्ता संपत्ति नहीं है? प्रमाणित उपयोगकर्ता का AppUser-Object कैसे प्राप्त करें?
कर्स्टन

13
@ कर्स्टन आप IHttpContextAccessorनिर्भरता इंजेक्शन के साथ प्राप्त कर सकते हैं और फिर Userhttp संदर्भ से प्राप्त कर सकते हैं । बस इस परम को सेवा वर्ग निर्माता में जोड़ें IHttpContextAccessor contextAccessor:। एक्सेसर को किसी फ़ील्ड पर रखें _contextAccessorऔर फिर सेवा विधियों पर इसे प्राप्त करें _contextAccessor.HttpContext.User
गेरार्डो ग्रिग्नोली

5
@ कर्स्टन, लेकिन इस कपल ने आपकी सेवा ASP.NET Core के साथ की, जिससे यह अन्य प्रकार के परिदृश्यों के लिए उपयोग करने योग्य नहीं है। यह आपके लिए स्वीकार्य हो सकता है, या नहीं। मैं यह भी पारित करने पर विचार करूंगा कि आप विधि कॉल पर सेवा में क्या चाहते हैं।
गेरार्डो ग्रिग्नोली

2
आपने मुझे सही तरीके से धक्का दिया: मैंने गेटअप और IsAuthenticated के साथ एक IUserService का निर्माण किया। मेरे ASP.NET कोर ऐप में मैं एक कार्यान्वयन उपयोगकर्ता सेवा है जो IHttpContextAccessor और UserManager <ApplicationUser> का उपयोग करता है। इसलिए मेरा userService ASP.NET Core से जुड़ा हुआ है, मेरी अन्य सेवाएँ नहीं हैं।
कर्स्टन

2
नहीं, वे डेटाबेस में नहीं जाते हैं। स्रोत की जाँच करते हुए, वे UserStore का उपयोग नहीं करते हैं। github.com/dotnet/corefx/blob/master/src/System.Security.Claims/... github.com/aspnet/Identity/blob/...
गेरार्डो Grignoli

34

अगर आप असर टोकन का उपयोग कर रहे हैं, तो उपरोक्त नमूने एक अनुप्रयोग उपयोगकर्ता वापस नहीं करते हैं।

इसके बजाय, इसका उपयोग करें:

ClaimsPrincipal currentUser = this.User;
var currentUserName = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;
ApplicationUser user = await _userManager.FindByNameAsync(currentUserName);

यह apsnetcore 2.0 में काम करता है। पहले के संस्करणों में कोशिश नहीं की है।


मेरे टोकन मान्य किए जा रहे हैं, लेकिन प्रिंसिपल और दावे सेट नहीं किए जा रहे हैं। यह
डॉटनेट

@ ps2goat, मैं इसे संबोधित करने के लिए एक नया प्रश्न बनाऊंगा, और उस कोड को शामिल करूंगा जो टोकन बना रहा है।
ग्रेग गम

1
मैं यह समझ गया। हमारे पास डिफ़ॉल्ट स्कीम नहीं है क्योंकि हमारे पास 5 अलग-अलग स्कीम हैं। मुझे टोकन को डीकोड करने के लिए एक मिडलवेयर जोड़ना था और वर्तमान उपयोगकर्ता को दावे सौंपने थे। मुझे शायद एक सवाल लिखना चाहिए और दूसरों के लिए इसका जवाब देना चाहिए, क्योंकि मेरी स्थिति के आसपास बहुत कम सामग्री है।
ps2goat

1
ClaimTypes.Name को वह यूजरनेम मिलता है जो मैं ईद की जगह देख रहा था। ClaimTypes.NameIdentifier को यूजर की Id मिलती है। बस अगर कोई इसे देखता है और सोच रहा है कि उपयोगकर्ता नाम कैसे प्राप्त करें। आपके उत्तर के लिए धन्यवाद ग्रेग!
मैथ्यू ज़ॉर्लियास

7

संदर्भ के लिए, मैंने ASP.NET Core 2 वेब एप्लिकेशन टेम्पलेट का उपयोग करके एक प्रोजेक्ट बनाया। फिर, वेब एप्लिकेशन (एमवीसी) चुनें फिर चेंज ऑथेंटिकेशन बटन पर क्लिक करें और इंडिविजुअल यूजर अकाउंट्स चुनें।

इस खाके से आपके लिए बहुत सारी बुनियादी सुविधाओं का निर्माण हुआ है। ManageControllerकंट्रोलर फ़ोल्डर में खोजें ।

इस ManageControllerवर्ग निर्माता को आबादी के लिए इस UserManager चर की आवश्यकता है:

private readonly UserManager<ApplicationUser> _userManager;

फिर, इस वर्ग में [HttpPost] सूचकांक विधि पर एक नज़र डालें। वे इस तरह से वर्तमान उपयोगकर्ता प्राप्त करते हैं:

var user = await _userManager.GetUserAsync(User);

एक बोनस नोट के रूप में, यह वह जगह है जहां आप उपयोगकर्ता प्रोफ़ाइल के लिए किसी भी कस्टम फ़ील्ड को अपडेट करना चाहते हैं जिसे आपने एस्पेनेटयूजर्स तालिका में जोड़ा है। फ़ील्ड को दृश्य में जोड़ें, फिर उन मानों को IndexViewModel में जमा करें जो तब इस पोस्ट विधि में सबमिट किए जाते हैं। ईमेल पता और फ़ोन नंबर सेट करने के लिए डिफ़ॉल्ट तर्क के बाद मैंने यह कोड जोड़ा:

user.FirstName = model.FirstName;
user.LastName = model.LastName;
user.Address1 = model.Address1;
user.Address2 = model.Address2;
user.City = model.City;
user.State = model.State;
user.Zip = model.Zip;
user.Company = model.Company;
user.Country = model.Country;
user.SetDisplayName();
user.SetProfileID();

_dbContext.Attach(user).State = EntityState.Modified;
_dbContext.SaveChanges();

5

.NET कोर 2.0 में उपयोगकर्ता पहले से ही अंतर्निहित विरासत नियंत्रक के हिस्से के रूप में मौजूद है। बस उपयोगकर्ता का उपयोग करें जैसा कि आप सामान्य रूप से करेंगे या किसी भी रिपॉजिटरी कोड में पास करेंगे।

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Policy = "TENANT")]
[HttpGet("issue-type-selection"), Produces("application/json")]
public async Task<IActionResult> IssueTypeSelection()
{
    try
    {
        return new ObjectResult(await _item.IssueTypeSelection(User));
    }
    catch (ExceptionNotFound)
    {
        Response.StatusCode = (int)HttpStatusCode.BadRequest;
        return Json(new
        {
            error = "invalid_grant",
            error_description = "Item Not Found"
        });
    }
}

यह वह जगह है जहाँ से यह विरासत में मिला है

#region Assembly Microsoft.AspNetCore.Mvc.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
// C:\Users\BhailDa\.nuget\packages\microsoft.aspnetcore.mvc.core\2.0.0\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.Core.dll
#endregion

using System;
using System.IO;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Routing;
using Microsoft.Net.Http.Headers;

namespace Microsoft.AspNetCore.Mvc
{
    //
    // Summary:
    //     A base class for an MVC controller without view support.
    [Controller]
    public abstract class ControllerBase
    {
        protected ControllerBase();

        //
        // Summary:
        //     Gets the System.Security.Claims.ClaimsPrincipal for user associated with the
        //     executing action.
        public ClaimsPrincipal User { get; }

2

बस अगर कोई भी दिलचस्पी रखता है तो यह मेरे लिए काम करता है। मेरे पास एक कस्टम पहचान है जो प्राथमिक कुंजी के लिए int का उपयोग करता है इसलिए मैं GetUserAsync विधि को ओवररोड करता हूं

GetUserAsync को ओवरराइड करें

public override Task<User> GetUserAsync(ClaimsPrincipal principal)
{
    var userId = GetUserId(principal);
    return FindByNameAsync(userId);
}

पहचान उपयोगकर्ता प्राप्त करें

var user = await _userManager.GetUserAsync(User);

यदि आप एक नियमित दिशानिर्देश प्राथमिक कुंजी का उपयोग कर रहे हैं तो आपको GetUserAsync को ओवरराइड करने की आवश्यकता नहीं है। यह सब मान रहा है कि आपने टोकन सही तरीके से कॉन्फ़िगर किया है।

public async Task<string> GenerateTokenAsync(string email)
{
    var user = await _userManager.FindByEmailAsync(email);
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(_tokenProviderOptions.SecretKey);

    var userRoles = await _userManager.GetRolesAsync(user);
    var roles = userRoles.Select(o => new Claim(ClaimTypes.Role, o));

    var claims = new[]
    {
        new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
        new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString(CultureInfo.CurrentCulture)),
        new Claim(JwtRegisteredClaimNames.GivenName, user.FirstName),
        new Claim(JwtRegisteredClaimNames.FamilyName, user.LastName),
        new Claim(JwtRegisteredClaimNames.Email, user.Email),
    }
    .Union(roles);

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(claims),
        Expires = DateTime.UtcNow.AddHours(_tokenProviderOptions.Expires),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };

    var token = tokenHandler.CreateToken(tokenDescriptor);

    return Task.FromResult(new JwtSecurityTokenHandler().WriteToken(token)).Result;
}

1
private readonly UserManager<AppUser> _userManager;

 public AccountsController(UserManager<AppUser> userManager)
 {
            _userManager = userManager;
 }

[Authorize(Policy = "ApiUser")]
[HttpGet("api/accounts/GetProfile", Name = "GetProfile")]
public async Task<IActionResult> GetProfile()
{
   var userId = ((ClaimsIdentity)User.Identity).FindFirst("Id").Value;
   var user = await _userManager.FindByIdAsync(userId);

   ProfileUpdateModel model = new ProfileUpdateModel();
   model.Email = user.Email;
   model.FirstName = user.FirstName;
   model.LastName = user.LastName;
   model.PhoneNumber = user.PhoneNumber;

   return new OkObjectResult(model);
}

0

मैंने अपने कंट्रोलर क्लास में कुछ इस तरह से डाला है और यह काम किया है:

IdentityUser user = await userManager.FindByNameAsync(HttpContext.User.Identity.Name);

जहाँ userManager Microsoft.AspNetCore.Identity.UserManager वर्ग का एक उदाहरण है (इसके साथ जाने वाले सभी अजीब सेटअप के साथ)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.