为什么在区域控制器加载时我的 BaseController.User 值 == null?

cha*_*986 1 c# asp.net-core-mvc asp.net-core

我正在编写一个 Asp.Net 核心应用程序,并且在获得导航访问权限之前,我让用户通过 Google 进行身份验证。当用户导航到我的“WorldBuilder”区域并点击 WorldController 时,BaseController.User 对象为空。这是迄今为止我设置的唯一区域/控制器。

用户在登录时有效,因为我可以迭代与用户关联的声明。我正在使用默认的 Asp.Net 核心谷歌身份验证,因此用户只会在登录页面上收到一个按钮,指示他们向谷歌进行身份验证。

[Authorize]
[Area("WorldBuilder")]
public class WorldController : Controller
{
    private string _userId;
    private IWorldService _worldService;
    private IUserRepository _userRepository;

    public WorldController(IWorldService worldService, IUserRepository userRepository)
    {
        if (User != null) /* The user object is found to be null here. */
        {
            var userIdNameClaim = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
            if (userIdNameClaim != null)
            {
                _userId = userIdNameClaim.Value;
            }
        }
        _userRepository = userRepository;
        _worldService = worldService;
    }
Run Code Online (Sandbox Code Playgroud)

我希望由于这些区域是同一应用程序的一部分,因此经过身份验证的用户信息将在区域之间传递,但情况似乎并非如此。BaseController.User 对象为 null

Hen*_*ema 5

您应该只从控制器的操作中访问该User属性(以及其他属性,例如HttpContext)。控制器是在执行身份验证和授权之前构造的,因此属性为空。

如果您需要对用户 ID 进行一般访问,您可以在控制器上创建一个属性,您可以在其中从用户对象中检索用户 ID,并从您的操作中使用该属性。您甚至可以将此属性移动到基类,并将该类用作基控制器,以便从每个控制器访问该属性。

例如:

public class ControllerBase : Controller
{
    public string UserId
    {
        get
        {
            if (User != null) /* The user object is found to be null here. */
            {
                var userIdNameClaim = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
                if (userIdNameClaim != null)
                {
                    return userIdNameClaim.Value;
                }
            }

            return null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

和您的特定控制器:

public class WorldController : ControllerBase
{

    // Contructor, etc...

    public IActionResult Get()
    {
       var userId = UserId;

       // Do something with userId (or use UserId directly)
    }

}
Run Code Online (Sandbox Code Playgroud)