繁体   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