簡體   English   中英

HttpContext.User 身份信息總是返回 null

[英]HttpContext.User Identity information always return null

我使用 .net 核心 3.1.6。 關於這個有很多答案,我每次都嘗試但都失敗了。 所以我創建了新的測試 MVC 項目並添加了身份驗證。

我嘗試使用“CurrentUserService”class 並獲取登錄的用戶信息。 但是,每次我得到 null 結果。

我的啟動.cs

public void ConfigureServices(IServiceCollection services) {
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddHttpContextAccessor();
    services.AddScoped<ICurrentUserService, CurrentUserService>();

    services.AddControllersWithViews();
    services.AddRazorPages();


}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    if (env.IsDevelopment()) {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else {
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints => {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapRazorPages();
    });
}

還有我的 CurrentUserService.cs

public class CurrentUserService : ICurrentUserService {
    private IHttpContextAccessor _httpContextAccessor;
    public CurrentUserService(IHttpContextAccessor httpContextAccessor) {
        _httpContextAccessor = httpContextAccessor;
    //I add x for test purpose and there is no user information here.
        var x = _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
    }

    public string UserId {
        get {
            var userIdClaim = _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
            return userIdClaim;
        }
    }

    public bool IsAuthenticated => UserId != null;
}

ICurrentUser.cs

public interface ICurrentUserService {
        string UserId { get; }
        bool IsAuthenticated { get; }
}

數據庫上下文.cs

public class ApplicationDbContext : IdentityDbContext {
        private readonly ICurrentUserService _currentUserService;

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options) {
        }

        public ApplicationDbContext(
            DbContextOptions<ApplicationDbContext> options,
            ICurrentUserService currentUserService)
            : base(options) {
            _currentUserService = currentUserService;
        }
    }

調試截圖: 在此處輸入圖像描述

HttpContext僅在請求期間有效。 Startup 中的Configure方法不是 web 調用,因此沒有HttpContext 當 .NET 核心為調用Configure創建ApplicationDbContext class 時,沒有有效的上下文。

當您發送請求Home/Index時,您可以在 controller 中獲取HttpContext

public class HomeController : Controller
{
    private IHttpContextAccessor _httpContextAccessor;

    public HomeController(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
        var x = _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); //get in the constructor
    }

    public IActionResult Index()
    {
        // you could also get in your method
        var x = _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
        return View();
    }
}

結果: 在此處輸入圖像描述

更新:

只有調用此服務,才能獲取數據:

public class HomeController : Controller
{
    private readonly ICurrentUserService _service;
    public HomeController(ICurrentUserService service)
    {
        _service = service;
    }

    public IActionResult Index()
    {
        var data = _service.UserId;
        return View();
    }
}

如果要獲取中間件中的數據,請檢查:

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();
app.Use(async (context, next) =>
{
    await next.Invoke();
    var data = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
});

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    endpoints.MapRazorPages();
});

更新2:

無論你用哪種方式創建ApplicationDbContext實例,除非你調用它,否則它無法單獨獲取服務。無論如何,你總是需要在下一個業務層調用服務。

簡單的方法是創建一個新方法,然后調用 ApplicationDbContext:

1.應用上下文:

public class ApplicationDbContext : IdentityDbContext
{
    private readonly ICurrentUserService _currentUserService;
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public ApplicationDbContext(
        DbContextOptions<ApplicationDbContext> options,
        ICurrentUserService currentUserService)
        : base(options)
    {
        _currentUserService = currentUserService;

    }
    public string GetId()
    {
        var data = _currentUserService.UserId;
        return data;
    }
}

2.Controller:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly ApplicationDbContext _context;
    public HomeController(ILogger<HomeController> logger, ApplicationDbContext context)
    {
        _context = context;
        _logger = logger;
    }

    public IActionResult Index()
    {
        var data = _context.GetId();
        return View();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM