วิธีรับ ID ผู้ใช้ที่ล็อกอินในปัจจุบันใน ASP.NET Core


179

ฉันเคยทำสิ่งนี้มาแล้วเมื่อใช้ MVC5 User.Identity.GetUserId()แต่ดูเหมือนจะไม่ทำงานที่นี่ User.Identityไม่ได้มีGetUserId()วิธีการ

ฉันใช้ Microsoft.AspNet.Identity


2
ลองนี้System.Web.HttpContext.Current.User.Identity.Name?
Pravin Deshmukh

ขอบคุณ @PravinDeshmukh แต่นั่นจะส่งคืนชื่อของผู้ใช้ไม่ใช่ ID
MRainzo

1
มันควรจะทำงาน ดูตัวอย่างใน asp.net github.com/aspnet/Identity/blob/... เพียงแค่ให้แน่ใจว่าผู้ใช้เข้าสู่ระบบ @PravinDeshmukh ไม่เคยใช้ System.Web.HttpContext.Current ใน vnext :)
960567

1
สวัสดี @ user960567 คุณช่วยบอกเราหน่อยได้ไหมว่าทำไม?
Pravin Deshmukh

@PravinDeshmukh เพราะมันจะไม่ทำงานบน. NET core และไม่มีการพึ่งพา System.Web
user960567

คำตอบ:


148

อัพเดทใน ASP.NET Core Version> = 2.0

ในตัวควบคุม:

public class YourControllerNameController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;

    public YourControllerNameController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task<IActionResult> YourMethodName()
    {
        var userId =  User.FindFirstValue(ClaimTypes.NameIdentifier) // will give the user's userId
        var userName =  User.FindFirstValue(ClaimTypes.Name) // will give the user's userName

        ApplicationUser applicationUser = await _userManager.GetUserAsync(User);
        string userEmail = applicationUser?.Email; // will give the user's Email
    }
}

ในชั้นเรียนอื่น ๆ :

public class OtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public OtherClass(IHttpContextAccessor httpContextAccessor)
    {
       _httpContextAccessor = httpContextAccessor;
    }

   public void YourMethodName()
   {
      var userId = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
   }
}

จากนั้นคุณควรลงทะเบียนIHttpContextAccessorในStartupชั้นเรียนดังต่อไปนี้:

public void ConfigureServices(IServiceCollection services)
{
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    // Or you can also register as follows

    services.AddHttpContextAccessor();
}

สำหรับวิธีการเขียนส่วนขยายที่สามารถอ่านได้เพิ่มเติมมีดังนี้:

public static class ClaimsPrincipalExtensions
{
    public static T GetLoggedInUserId<T>(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        var loggedInUserId = principal.FindFirstValue(ClaimTypes.NameIdentifier);

        if (typeof(T) == typeof(string))
        {
            return (T)Convert.ChangeType(loggedInUserId, typeof(T));
        }
        else if (typeof(T) == typeof(int) || typeof(T) == typeof(long))
        {
            return loggedInUserId != null ? (T)Convert.ChangeType(loggedInUserId, typeof(T)) : (T)Convert.ChangeType(0, typeof(T));
        }
        else
        {
            throw new Exception("Invalid type provided");
        }
    }

    public static string GetLoggedInUserName(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        return principal.FindFirstValue(ClaimTypes.Name);
    }

    public static string GetLoggedInUserEmail(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        return principal.FindFirstValue(ClaimTypes.Email);
    }
}

จากนั้นใช้ดังต่อไปนี้:

public class YourControllerNameController : Controller
{
    public IActionResult YourMethodName()
    {
        var userId = User.GetLoggedInUserId<string>(); // Specify the type of your UserId;
        var userName = User.GetLoggedInUserName();
        var userEmail = User.GetLoggedInUserEmail();
    }
}

public class OtherClass
{
     private readonly IHttpContextAccessor _httpContextAccessor;
     public OtherClass(IHttpContextAccessor httpContextAccessor)
     {
         _httpContextAccessor = httpContextAccessor;
     }

     public void YourMethodName()
     {
         var userId = _httpContextAccessor.HttpContext.User.GetLoggedInUserId<string>(); // Specify the type of your UserId;
     }
}

1
แต่ผู้ใช้คืนค่า null ในกรณีของฉันหรือไม่ ฉันทำผิดตรงไหน
Sruthi Varghese

คุณแน่ใจหรือว่าคุณลงชื่อเข้าใช้ด้วยผู้ใช้?
TanvirArjel

สถานการณ์ของฉันเป็นเหมือนฉันต้องการชื่อผู้ใช้ของผู้ใช้ที่เข้าสู่ระบบของฉัน ปล่อยให้เป็น Ubuntu หรือ Windows และในขณะที่ฉันกำลังทดสอบสิ่งนี้ในหน้าต่างฉันกำลังลงชื่อเข้าใช้ภายใต้ชื่อ Namee ของฉัน nullแต่มันกลับมา
Sruthi Varghese

จากนั้นต้องดูรหัสของคุณ! อาจเป็นตัวแทนภายนอกที่มีบทบาทที่นี่
TanvirArjel

2
ฉันพบว่าหากคุณได้รับผลลัพธ์ที่User.Identity.Nameไม่ดีอาจเป็นเพราะมีการเปิดใช้งานการตรวจสอบสิทธิ์แบบไม่ระบุชื่อ ผมสามารถที่จะได้รับUser.Identity.Nameที่จะกลับโดเมนและชื่อผู้ใช้ของฉันโดยการขยายตัวProperties > launchSettings.jsonและการตั้งค่าanonymousAuthenticationการfalseและการwindowsAuthentication true
Andrew Grey

109

จนถึง ASP.NET Core 1.0 RC1 :

มันเป็น User.GetUserId () จากSystem.Security.Claims namespace

ตั้งแต่ ASP.NET Core 1.0 RC2 :

ตอนนี้คุณต้องใช้UserManager คุณสามารถสร้างวิธีการรับผู้ใช้ปัจจุบัน:

private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(HttpContext.User);

และรับข้อมูลผู้ใช้กับวัตถุ:

var user = await GetCurrentUserAsync();

var userId = user?.Id;
string mail = user?.Email;

หมายเหตุ: คุณสามารถทำได้โดยไม่ต้องใช้วิธีการเขียนบรรทัดเดียวเช่นนี้string mail = (await _userManager.GetUserAsync(HttpContext.User))?.Emailแต่ไม่เคารพหลักการความรับผิดชอบเดียว เป็นการดีกว่าที่จะแยกวิธีที่คุณได้รับผู้ใช้เพราะถ้าวันหนึ่งคุณตัดสินใจที่จะเปลี่ยนระบบการจัดการผู้ใช้ของคุณเช่นใช้โซลูชันอื่นที่ไม่ใช่ Identity มันจะเจ็บปวดเพราะคุณต้องทบทวนรหัสทั้งหมดของคุณ


1
ฉันมี System.Security.Claims namespace และแอสเซมบลี Microsoft.AspNet.Identity
เทล

2
ฉันคิดว่าคำตอบนี้ดีกว่าคำตอบที่ยอมรับโดยเฉพาะอย่างยิ่งตั้งแต่หลัก asp.net คือการส่งเสริมการฉีดพึ่งพา
Phillip Davis

2
ดูเหมือนว่าผิดเพราะ userManager จะทำการร้องขอไปยังฐานข้อมูลเพื่อดึงข้อมูลเกี่ยวกับผู้ใช้ และในกรณีนี้ userId มีอยู่แล้วใน HttpContext ผู้ใช้
ไม่ระบุตัวตน

@incognito ตัวระบุเป็นเพียงตัวอย่าง แต่คุณสามารถรับข้อมูลทั้งหมดที่คุณต้องการด้วยวัตถุของผู้ใช้
AdrienTorris

2
@Adrien แต่คำถามคือทำอย่างไรถึงจะได้รับ ID ผู้ใช้ แค่อยากจะบอกว่าวิธีที่ให้มานั้นไม่ได้มีประสิทธิภาพมากที่สุด สำหรับกรณีนี้ฉันต้องการคำตอบโดย Soren หรือรุ่นที่สั้นกว่าซึ่งสามารถพบได้ในความคิดเห็น
ไม่ระบุตัวตน

91

คุณสามารถรับมันในตัวควบคุมของคุณ:

using System.Security.Claims;
var userId = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

หรือเขียนวิธีการขยายเหมือนก่อน. Core v1.0

using System;
using System.Security.Claims;

namespace Shared.Web.MvcExtensions
{
    public static class ClaimsPrincipalExtensions
    {
        public static string GetUserId(this ClaimsPrincipal principal)
        {
            if (principal == null)
                throw new ArgumentNullException(nameof(principal));

            return principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        }
    }
}

และรับทุกที่ที่ผู้ใช้ ClaimsPrincipal พร้อมใช้งาน :

using Microsoft.AspNetCore.Mvc;
using Shared.Web.MvcExtensions;

namespace Web.Site.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return Content(this.User.GetUserId());
        }
    }
}

16
รุ่นที่สั้นกว่า:var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
CFreitas

1
โปรดทราบว่าวิธีการขยายนี้ใช้งานได้เฉพาะกับผู้ใช้งานในส่วนควบคุมเท่านั้นไม่ใช่ดูองค์ประกอบเนื่องจากองค์ประกอบมุมมองผู้ใช้เป็น IPrincipal
adam3039

@AK คุณสามารถใช้Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier))เพื่อรับจำนวนผู้ใช้
Hamza Khanzada

1
@HamzaKhanzada ใช่มันใช้งานได้ แต่ดูยาวและน่าเกลียดมาก
AK

39

ฉันรวมโดยใช้ System.Security.Claims และฉันสามารถเข้าถึงวิธีการขยาย GetUserId ()

หมายเหตุ: ฉันมีการใช้ Microsoft.AspNet.Identity แล้ว แต่ไม่สามารถรับวิธีการขยายได้ ดังนั้นฉันเดาว่าทั้งคู่ต้องใช้ร่วมกัน

using Microsoft.AspNet.Identity;
using System.Security.Claims;

แก้ไข : คำตอบนี้ล้าสมัยแล้ว ดูคำตอบของโซเรนหรือเอเดรียนสำหรับวิธีลงวันที่เพื่อบรรลุเป้าหมายใน CORE 1.0


17
นี่คือซอสลับ แต่สำหรับทุกคนระวังหลังจากที่คุณเพิ่มการใช้เหล่านี้มันเป็น ... var userId = User.GetUserId();
Samurai Ken

4
.GetUserId () ส่วนขยายจาก ClaimsPrincipal (Controller.User) ถูกย้ายไปที่ => UserManager.GetUserId (ผู้ใช้);
Soren

1
ใช้ System.Security.Claims; var userId = this.User.FindFirst (ClaimTypes.NameIdentifier);
เปลี่ยน

3
ยกนิ้วให้สำหรับคำตอบที่ถูกต้องก่อนหน้านี้และระบุคำตอบ "ถูกต้อง" ใหม่อย่างถูกต้อง
pimbrouwers

26

สำหรับ. NET Core 2.0 เท่านั้นข้อมูลต่อไปนี้จำเป็นต้องดึง ID ผู้ใช้ของผู้ใช้ที่เข้าสู่ระบบในControllerคลาส:

var userId = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

หรือ

var userId = HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);

เช่น

contact.OwnerID = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

17

ตามที่ระบุไว้ที่ไหนสักแห่งในโพสต์นี้วิธีการ GetUserId () ได้ถูกย้ายไปยัง UserManager

private readonly UserManager<ApplicationUser> _userManager;

public YourController(UserManager<ApplicationUser> userManager)
{
    _userManager = userManager;
}

public IActionResult MyAction()
{
    var userId = _userManager.GetUserId(HttpContext.User);

    var model = GetSomeModelByUserId(userId);

    return View(model);
}

หากคุณเริ่มโครงการที่ว่างเปล่าคุณอาจต้องเพิ่ม UserManger ในบริการของคุณใน startup.cs มิฉะนั้นจะเกิดกรณีนี้ขึ้น


10

คุณต้องนำเข้า Microsoft.AspNetCore.Identity & System.Security.Claims

// to get current user ID
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);

// to get current user info
var user = await _userManager.FindByIdAsync(userId);

จากทั้งหมด anwsers ของคุณเป็นคนเดียวที่ทำงานกับ ASP.NET CORE v 2.0 Congratz!
ยุติธรรมเพียง

นี่ไง. ทุกคนจาก. NET Core 2.0 ขึ้นไปนี่คือคำตอบของคุณ
alvinchesaro

1
ทดสอบบน. NET Core 3.1 ในการตั้งค่า Web API + JWT ฉันต้องการให้ผู้ใช้ที่ลงชื่อเข้าใช้อยู่ในตัวควบคุมฐานซึ่งไม่ได้ผลการสอบถามผู้ใช้จากฐานข้อมูลสำหรับทุกคำขอ ฯลฯ มีวิธีใดที่จะรับผู้ใช้ปัจจุบันโดยไม่ต้องสืบค้นฐานข้อมูลหรือไม่
Nexus

ทำไมเหมืองกลับ"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"สำหรับUser.FindFirstValue(ClaimTypes.NameIdentifier);?
ไร้สาระ

5

แม้ว่าคำตอบของ Adrien นั้นถูกต้องคุณสามารถทำได้ทั้งหมดในบรรทัดเดียว ไม่จำเป็นต้องมีฟังก์ชั่นหรือระเบียบเพิ่มเติม

มันใช้งานได้ฉันตรวจสอบใน ASP.NET Core 1.0

var user = await _userManager.GetUserAsync(HttpContext.User);

แล้วคุณจะได้รับคุณสมบัติอื่น ๆ user.Emailของตัวแปรเช่น ฉันหวังว่านี่จะช่วยให้ใครบางคน


3
เหตุผลที่ฉันใช้เมธอดคือการเคารพหลักการความรับผิดชอบเดียว หากคุณไม่แยกวิธีที่คุณได้รับผู้ใช้มันจะลำบากถ้าคุณตัดสินใจปรับเปลี่ยนระบบการจัดการผู้ใช้เช่นใช้โซลูชันอื่นที่ไม่ใช่ Identity
AdrienTorris

5

สำหรับ ASP.NET Core 2.0, Entity Framework Core 2.0, AspNetCore.Identity 2.0 api ( https://github.com/kkagill/ContosoUniversity-Backend ):

Idก็เปลี่ยนไปUser.Identity.Name

    [Authorize, HttpGet("Profile")]
    public async Task<IActionResult> GetProfile()
    {
        var user = await _userManager.FindByIdAsync(User.Identity.Name);

        return Json(new
        {
            IsAuthenticated = User.Identity.IsAuthenticated,
            Id = User.Identity.Name,
            Name = $"{user.FirstName} {user.LastName}",
            Type = User.Identity.AuthenticationType,
        });
    }

การตอบสนอง:

ป้อนคำอธิบายรูปภาพที่นี่


จากการทดสอบของฉันthis.User.Identity.Nameมีแนวโน้มที่จะเป็นชื่อผู้ใช้ ในการทดสอบของฉันชื่อผู้ใช้คืออีเมลเป็นผู้ใช้เข้าสู่ระบบจากการลงทะเบียนหรือเข้าสู่ระบบจากการเข้าสู่ระบบภายนอก (เช่น Facebook, Google) รหัสต่อไปนี้จะส่งคืน userId ฉันใช้คีย์หลักที่เพิ่มขึ้นอัตโนมัติสำหรับตารางผู้ใช้ข้อมูลประจำตัวของฉันดังนั้น int.Parse int userId = int.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
Michael Buen

1
FindByIdAsyncไม่ทำงานเนื่องจากคุณระบุชื่อผู้ใช้ FindByNameAsyncมันทำงานได้เมื่อคุณเปลี่ยนได้โดย
แจสเปอร์

4

ใน APiController

User.FindFirst(ClaimTypes.NameIdentifier).Value

อย่างนี้คุณจะได้รับการเรียกร้อง


1

User.Identity.GetUserId ();

ไม่มีอยู่ใน asp.net identity core 2.0 ในเรื่องนี้ฉันมีวิธีการจัดการที่แตกต่างกัน ฉันได้สร้างคลาสทั่วไปสำหรับใช้ทั้งแอปพลิเคชันเนื่องจากการรับข้อมูลผู้ใช้

สร้าง PCommon คลาสทั่วไปและอินเทอร์เฟซ IPCommon เพิ่มการอ้างอิงusing System.Security.Claims

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Common.Web.Helper
{
    public class PCommon: IPCommon
    {
        private readonly IHttpContextAccessor _context;
        public PayraCommon(IHttpContextAccessor context)
        {
            _context = context;
        }
        public int GetUserId()
        {
            return Convert.ToInt16(_context.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier));
        }
        public string GetUserName()
        {
            return _context.HttpContext.User.Identity.Name;
        }

    }
    public interface IPCommon
    {
        int GetUserId();
        string GetUserName();        
    }    
}

นี่คือการดำเนินการของชั้นเรียนทั่วไป

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using Pay.DataManager.Concreate;
using Pay.DataManager.Helper;
using Pay.DataManager.Models;
using Pay.Web.Helper;
using Pay.Web.Models.GeneralViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Pay.Controllers
{

    [Authorize]
    public class BankController : Controller
    {

        private readonly IUnitOfWork _unitOfWork;
        private readonly ILogger _logger;
        private readonly IPCommon _iPCommon;


        public BankController(IUnitOfWork unitOfWork, IPCommon IPCommon, ILogger logger = null)
        {
            _unitOfWork = unitOfWork;
            _iPCommon = IPCommon;
            if (logger != null) { _logger = logger; }
        }


        public ActionResult Create()
        {
            BankViewModel _bank = new BankViewModel();
            CountryLoad(_bank);
            return View();
        }

        [HttpPost, ActionName("Create")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Insert(BankViewModel bankVM)
        {

            if (!ModelState.IsValid)
            {
                CountryLoad(bankVM);
                //TempData["show-message"] = Notification.Show(CommonMessage.RequiredFieldError("bank"), "Warning", type: ToastType.Warning);
                return View(bankVM);
            }


            try
            {
                bankVM.EntryBy = _iPCommon.GetUserId();
                var userName = _iPCommon.GetUserName()();
                //_unitOfWork.BankRepo.Add(ModelAdapter.ModelMap(new Bank(), bankVM));
                //_unitOfWork.Save();
               // TempData["show-message"] = Notification.Show(CommonMessage.SaveMessage(), "Success", type: ToastType.Success);
            }
            catch (Exception ex)
            {
               // TempData["show-message"] = Notification.Show(CommonMessage.SaveErrorMessage("bank"), "Error", type: ToastType.Error);
            }
            return RedirectToAction(nameof(Index));
        }



    }
}

รับ userId และชื่อในการกระทำแทรก

_iPCommon.GetUserId();

ขอบคุณ Maksud


1
คุณต้องลงทะเบียน IHttpContextAccessor ใน Startup.cs หรือไม่
REMESQ

1
ไม่มี REMESQ ฉันไม่ได้ฉีดสิ่งนี้ลงในการเริ่มต้น แต่ทำงานในแอปพลิเคชันของฉัน
Maksud

1

สำหรับการรับรหัสผู้ใช้ปัจจุบันในมุมมองมีดโกนเราสามารถฉีด UserManager ในมุมมองดังนี้:

@inject Microsoft.AspNetCore.Identity.UserManager<ApplicationUser> _userManager
@{ string userId = _userManager.GetUserId(User); }

ฉันหวังว่าคุณพบว่ามีประโยชน์.


0

ใช้สามารถใช้

string userid = User.FindFirst("id").Value;

ด้วยเหตุผลบางอย่าง NameIdentifier ตอนนี้ดึงชื่อผู้ใช้ (.net core 2.2)


0

ในฐานะผู้ดูแลระบบที่ทำงานกับโปรไฟล์ของคนอื่นและคุณต้องได้รับ Id ของโปรไฟล์ที่คุณกำลังทำงานอยู่คุณสามารถใช้ ViewBag เพื่อจับภาพรหัสเช่น ViewBag.UserId = userId; ในขณะที่ userId เป็นพารามิเตอร์สตริงของวิธีการที่คุณกำลังทำงานอยู่

    [HttpGet]

    public async Task<IActionResult> ManageUserRoles(string userId)
    {

          ViewBag.UserId = userId;


        var user = await userManager.FindByIdAsync(userId);

        if (user == null)
        {
            ViewBag.ErrorMessage = $"User with Id = {userId} cannot be found";
            return View("NotFound");
        }

        var model = new List<UserRolesViewModel>();

        foreach (var role in roleManager.Roles)
        {
            var userRolesViewModel = new UserRolesViewModel
            {
                RoleId = role.Id,
                RoleName = role.Name
            };

            if (await userManager.IsInRoleAsync(user, role.Name))
            {
                userRolesViewModel.IsSelected = true;
            }
            else
            {
                userRolesViewModel.IsSelected = false;
            }

            model.Add(userRolesViewModel);
        }
        return View(model);
    }

-11

หากคุณต้องการสิ่งนี้ใน ASP.NET MVC Controller ให้ใช้

using Microsoft.AspNet.Identity;

User.Identity.GetUserId();

คุณต้องเพิ่มusingคำสั่งเพราะGetUserId()จะไม่อยู่ที่นั่นหากไม่มี


2
ใช่ฉันรวมอยู่ในคำถามที่ฉันมี "ใช้ Microsoft.AspNet.Identity" ฉันคิดหาวิธีแก้มันด้วยคำตอบของฉันที่โพสต์
MRainzo

1
FWIW มัน (ตอนนี้) User.GetUserId()และไม่ใช่User.Identity.GetUserId()
lc

18
คำถามคือและเป็น abou asp.net CORE ซึ่งมีเนมสเปซ Microsoft.AspNetCore.Identity และไม่ใช่ Microsoft.AspNet.Identity; และการใช้เนมสเปซใหม่นั้นจะไม่มีวิธีการขยาย GetUserId () คำตอบนี้ผิด!
ปาสกาล

4
ง่ายในทุกแคป และเรียนรู้เกี่ยวกับการเป็นคนดีใน SO stackoverflow.blog/2018/04/26/…
smoore4
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.