Cara mendapatkan ID pengguna saat ini yang login di ASP.NET Core

179

Saya telah melakukan ini sebelumnya dengan menggunakan MVC5 User.Identity.GetUserId()tetapi sepertinya tidak bekerja di sini. Tidak User.Identitymemiliki GetUserId()metode

saya menggunakan Microsoft.AspNet.Identity

MRainzo
sumber
2
coba ini System.Web.HttpContext.Current.User.Identity.Name?
Pravin Deshmukh
Terima kasih @PravinDeshmukh tapi itu mengembalikan nama pengguna dan bukan id
MRainzo
1
Itu harus bekerja. Lihat contoh di asp.net github.com/aspnet/Identity/blob/… . Pastikan pengguna sudah masuk. @PravinDeshmukh, jangan pernah gunakan System.Web.HttpContext.Current in vnext :)
user960567
1
Hai @ user960567, bisakah Anda memberi tahu kami alasannya?
Pravin Deshmukh
@PravinDeshmukh karena itu tidak akan bekerja pada .NET core dan tidak ada ketergantungan System.Web.
user960567

Jawaban:

148

Pembaruan dalam ASP.NET Core Version> = 2.0

Dalam Kontroler:

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
    }
}

Di beberapa kelas lain:

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

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

Maka Anda harus mendaftar IHttpContextAccessordi Startupkelas sebagai berikut:

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

    // Or you can also register as follows

    services.AddHttpContextAccessor();
}

Untuk lebih mudah dibaca, tulis metode ekstensi sebagai berikut:

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);
    }
}

Kemudian gunakan sebagai berikut:

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;
     }
}
TanvirArjel
sumber
1
Tetapi Pengguna mengembalikan nol dalam kasus saya? Di mana saya melakukan kesalahan?
Sruthi Varghese
Apakah Anda yakin masuk dengan pengguna?
TanvirArjel
Skenario saya seperti saya ingin nama pengguna pengguna masuk ke sistem saya. Biarkan itu Ubuntu atau Windows? Dan ketika saya sedang menguji ini di windows saya login di bawah nama saya. Tapi itu kembali null.
Sruthi Varghese
Maka harus melihat kode Anda! Mungkin ada agen eksternal yang berperan di sini.
TanvirArjel
2
Saya telah menemukan bahwa jika Anda mendapat hasil nol User.Identity.Name, itu bisa jadi karena Otentikasi Anonim diaktifkan. Saya dapat User.Identity.Namemengembalikan domain dan nama pengguna saya dengan memperluas Properties > launchSettings.json, dan mengatur anonymousAuthenticationke false, dan windowsAuthenticationke true.
Andrew Gray
109

Hingga ASP.NET Core 1.0 RC1 :

Itu adalah User.GetUserId () dari System.Security.Claims namespace.

Sejak ASP.NET Core 1.0 RC2 :

Anda sekarang harus menggunakan UserManager . Anda dapat membuat metode untuk mendapatkan pengguna saat ini:

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

Dan dapatkan informasi pengguna dengan objek:

var user = await GetCurrentUserAsync();

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

Catatan: Anda dapat melakukannya tanpa menggunakan metode penulisan satu baris seperti ini string mail = (await _userManager.GetUserAsync(HttpContext.User))?.Email, tetapi itu tidak menghormati prinsip tanggung jawab tunggal. Lebih baik mengisolasi cara Anda mendapatkan pengguna karena jika suatu hari Anda memutuskan untuk mengubah sistem manajemen pengguna Anda, seperti menggunakan solusi lain dari Identity, itu akan menyakitkan karena Anda harus meninjau seluruh kode Anda.

AdrienTorris
sumber
1
Saya memiliki namespace System.Security.Claims dan perakitan Microsoft.AspNet.Identity.
scottheckel
2
Saya pikir jawaban ini lebih baik daripada jawaban yang diterima terutama karena inti asp.net mempromosikan injeksi ketergantungan.
Phillip Davis
2
Tampaknya cara yang salah karena userManager akan membuat permintaan ke database untuk mengambil informasi tentang pengguna. Dan dalam hal ini, userId sudah tersedia di HttpContext.User
incognito
@incognito Identifier hanyalah sebuah contoh tetapi Anda bisa mendapatkan semua informasi yang Anda butuhkan dengan objek pengguna
AdrienTorris
2
@Adrien tetapi pertanyaannya adalah bagaimana cara mendapatkan User Id. Hanya ingin mengatakan bahwa cara yang disediakan bukan yang paling efisien. Untuk kasus ini saya lebih suka jawaban oleh Soren atau versi yang lebih pendek yang dapat ditemukan di komentar.
incognito
91

Anda bisa mendapatkannya di controller Anda:

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

atau tulis metode ekstensi seperti sebelumnya .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;
        }
    }
}

dan dapatkan dimanapun Klaim penggunaPrincipal tersedia :

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

namespace Web.Site.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return Content(this.User.GetUserId());
        }
    }
}
Soren
sumber
16
Versi lebih pendek:var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
CFreitas
1
Perhatikan bahwa metode ekstensi ini hanya berfungsi untuk pengontrol di dalam Pengguna, bukan melihat komponen, karena komponen tampilan yang digunakan Pengguna adalah IPrincipal
adam3039
@ AK dapat Anda gunakan Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier))untuk mendapatkan integer UserId
Hamza Khanzada
1
@ HamzaKhanzada Yap, ini berfungsi, tetapi terlihat sangat panjang dan jelek.
AK
39

Saya termasuk menggunakan System.Security.Claims dan saya bisa mengakses metode ekstensi GetUserId ()

NB: Saya sudah menggunakan Microsoft.AspNet.Identity tetapi tidak bisa mendapatkan metode ekstensi. Jadi saya kira keduanya harus digunakan bersama satu sama lain

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

EDIT : Jawaban ini sudah usang. Lihatlah jawaban Soren atau Adrien untuk mengetahui cara pencapaiannya di CORE 1.0

MRainzo
sumber
17
Ini adalah saus rahasia, tetapi bagi siapa pun yang mencari setelah menambahkan ini, ini adalah ... var userId = User.GetUserId();
Samurai Ken
4
ekstensi .GetUserId () dari ClaimsPrincipal (Controller.User) telah dipindahkan ke => UserManager.GetUserId (Pengguna);
Soren
1
menggunakan System.Security.Claims; var userId = this.User.FindFirst (ClaimTypes.NameIdentifier);
Beralih
3
Jempol untuk jawaban yang sebelumnya valid, dan mengidentifikasi dengan benar jawaban "benar" yang baru.
pimbrouwers
26

Hanya untuk .NET Core 2.0 Berikut ini diperlukan untuk mengambil UserID dari Pengguna yang log in di Controllerkelas:

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

atau

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

misalnya

contact.OwnerID = this.User.FindFirstValue(ClaimTypes.NameIdentifier);
Laki-laki yang luar biasa
sumber
17

Sebagaimana dinyatakan di suatu tempat dalam posting ini, metode GetUserId () telah dipindahkan ke 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);
}

Jika Anda memulai proyek kosong, Anda mungkin perlu menambahkan UserManger ke layanan Anda di startup.cs. Kalau tidak, ini seharusnya sudah menjadi masalahnya.

Menno Guldemond
sumber
10

Anda harus mengimpor 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);
Mansur Haider
sumber
dari semua ini, milik Anda adalah satu-satunya yang bekerja dengan ASP.NET CORE v 2.0. Selamat!
Just Fair
ini dia. Siapa saja dari .NET Core 2.0 dan di atasnya, ini adalah jawaban Anda
alvinchesaro
1
Diuji pada .NET Core 3.1 dalam pengaturan Web API + JWT. Saya ingin pengguna yang saat ini masuk dalam pengendali basis, ini tidak efisien, meminta pengguna dari database untuk setiap permintaan, dll. Apakah ada cara untuk mendapatkan pengguna saat ini tanpa meminta database?
Nexus
mengapa saya kembali "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"untuk User.FindFirstValue(ClaimTypes.NameIdentifier);?
puerile
5

Meskipun jawaban Adrien benar, Anda dapat melakukan ini semua dalam satu baris. Tidak perlu fungsi tambahan atau kekacauan.

Berhasil saya memeriksanya di ASP.NET Core 1.0

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

maka Anda bisa mendapatkan properti lain seperti variabel user.Email. Saya harap ini membantu seseorang.

Ahmad
sumber
3
Alasan mengapa saya menggunakan metode adalah untuk menghormati prinsip responsabilitas tunggal. Jika Anda tidak mengisolasi cara Anda mendapatkan pengguna, itu akan menyakitkan jika suatu hari Anda memutuskan untuk memodifikasi sistem manajemen pengguna Anda, seperti menggunakan solusi lain selain Identity.
AdrienTorris
5

Untuk ASP.NET Core 2.0, Entity Framework Core 2.0, AspNetCore.Identity 2.0 api ( https://github.com/kkagill/ContosoUniversity-Backend ):

Itu Iddiubah menjadiUser.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,
        });
    }

Tanggapan:

masukkan deskripsi gambar di sini

jv_
sumber
Berdasarkan pengujian saya, this.User.Identity.Namecenderung menjadi nama pengguna. Pada pengujian saya, nama pengguna adalah email, menjadi pengguna masuk dari pendaftaran atau masuk dari login eksternal (misalnya, Facebook, Google). Kode berikut mengembalikan userId. Saya menggunakan kunci primer yang ditambahkan secara otomatis untuk tabel pengguna identitas saya, karenanya int.Parse. int userId = int.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
Michael Buen
1
FindByIdAsynctidak berfungsi karena Anda memberikan nama pengguna. Ini berfungsi saat Anda menggantinya dengan FindByNameAsync.
Jasper
4

dalam APiController

User.FindFirst(ClaimTypes.NameIdentifier).Value

Sesuatu seperti ini, Anda akan mendapatkan klaim

Usman
sumber
1

User.Identity.GetUserId ();

tidak ada di asp.net identity core 2.0. dalam hal ini, saya telah berhasil dengan cara yang berbeda. Saya telah membuat kelas umum untuk menggunakan seluruh aplikasi, karena mendapatkan informasi pengguna.

buat kelas umum PCommon & antarmuka IPCommon menambahkan referensiusing 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();        
    }    
}

Di sini implementasi kelas bersama

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));
        }



    }
}

dapatkan userId dan nama dalam aksi sisipkan

_iPCommon.GetUserId();

Terima kasih, Maksud

Maksud
sumber
1
Apakah Anda harus mendaftar IHttpContextAccessor di Startup.cs?
REMESQ
1
Tidak REMESQ, saya tidak menyuntikkan ini ke startup, tetapi bekerja di aplikasi saya
Maksud
1

Untuk mendapatkan id pengguna saat ini dalam tampilan silet, kami dapat menyuntikkan UserManager dalam tampilan seperti ini:

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

Semoga bermanfaat.

HO3EiN
sumber
0

gunakan bisa menggunakan

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

untuk beberapa alasan NameIdentifier sekarang mengambil nama pengguna (.net core 2.2)

Mosta
sumber
0

Sebagai administrator yang bekerja pada profil orang lain dan Anda perlu mendapatkan ID dari profil yang sedang Anda kerjakan, Anda dapat menggunakan ViewBag untuk menangkap Id misalnya ViewBag.UserId = userId; sementara userId adalah Parameter string dari metode yang sedang Anda kerjakan.

    [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);
    }
sammy Akinsoju
sumber
-11

Jika Anda menginginkan ini di ASP.NET MVC Controller, gunakan

using Microsoft.AspNet.Identity;

User.Identity.GetUserId();

Anda perlu menambahkan usingpernyataan karena GetUserId()tidak akan ada di sana tanpanya.

Pravin Deshmukh
sumber
2
Ya, saya termasuk dalam pertanyaan bahwa saya memiliki "menggunakan Microsoft.AspNet.Identity". Saya menemukan cara untuk menyelesaikannya dengan jawaban saya di pos
MRainzo
1
FWIW itu (sekarang) User.GetUserId()dan tidakUser.Identity.GetUserId()
lc.
18
Pertanyaannya adalah abou asp.net CORE yang memiliki namespace Microsoft.AspNetCore.Identity; dan BUKAN Microsoft.AspNet.Identity; Dan menggunakan namespace baru tidak ada metode ekstensi NO GetUserId (). JAWABAN INI SALAH!
Pascal
4
Mudah di SEMUA CAPS. Dan belajar tentang bersikap baik pada SO. stackoverflow.blog/2018/04/26/…
smoore4