简体   繁体   English

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

[英]HttpContext.User Identity information always return null

I use .net core 3.1.6.我使用 .net 核心 3.1.6。 There are lots of answer about this and I try all but failed each time.关于这个有很多答案,我每次都尝试但都失败了。 So I create new test MVC project and add authentication.所以我创建了新的测试 MVC 项目并添加了身份验证。

I try to use a "CurrentUserService" class and get logged user information.我尝试使用“CurrentUserService”class 并获取登录的用户信息。 However, every each time I get null result.但是,每次我得到 null 结果。

My startup.cs我的启动.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();
    });
}

And my CurrentUserService.cs还有我的 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 ICurrentUser.cs

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

DbContext.cs数据库上下文.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;
        }
    }

Debug screenshoot:调试截图: 在此处输入图像描述

HttpContext is only valid during a request.The Configure method in Startup is not a web call and, as such, does not have a HttpContext . HttpContext仅在请求期间有效。 Startup 中的Configure方法不是 web 调用,因此没有HttpContext When .NET Core creates an ApplicationDbContext class for the call to Configure there is no valid context.当 .NET 核心为调用Configure创建ApplicationDbContext class 时,没有有效的上下文。

You could get the HttpContext in the controller when you send request Home/Index :当您发送请求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();
    }
}

Result:结果: 在此处输入图像描述

Update:更新:

Only if you call this service,then you could get the data:只有调用此服务,才能获取数据:

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

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

If you want to get the data in the middleware,please check:如果要获取中间件中的数据,请检查:

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

Update2:更新2:

No matter which way you create the ApplicationDbContext instance,it could not separately get the service unless you call it.Anyway,you always need to call the service in the next business layer.无论你用哪种方式创建ApplicationDbContext实例,除非你调用它,否则它无法单独获取服务。无论如何,你总是需要在下一个业务层调用服务。

The simple way is to create a new method then you call ApplicationDbContext:简单的方法是创建一个新方法,然后调用 ApplicationDbContext:

1.ApplicationContext: 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: 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