简体   繁体   English

将JWT发送到新控制器后如何获取用户信息

[英]How to get user information after sending JWT to a new controller

I'm working on an ASP.Net Core API project. 我正在研究ASP.Net Core API项目。

There are 2 controllers, controller A and B, I use Postman to pass my username and password to controller A action method, and it successfully returns a JWT. 有两个控制器,控制器A和B,我使用Postman将用户名和密码传递给控制器​​A的操作方法,它成功返回了JWT。 After I pass the JWT to controller B, I hope to get the username and role information of the credential which I had input into the controller A. 将JWT传递给控制器​​B后,希望获得输入到控制器A中的凭证的用户名和角色信息。

The code in controller B below shows the way I get the user info. 下面控制器B中的代码显示了我获取用户信息的方式。

public async Task<ActionResult> Get()
        {
            var user = await _userManager.GetUserAsync(HttpContext.User);
            var role = await _userManager.GetRolesAsync(user);
            return Ok(user);
        }

But after I sent the JWT, I got null user. 但是在发送JWT之后,我得到了空用户。

在此处输入图片说明

Edit1: EDIT1:

ConfigureServices method in my Startup.cs: 我的Startup.cs中的ConfigureServices方法:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateIssuerSigningKey = true,
                        ValidIssuer = "issuer",
                        ValidAudience = "audience",
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("This is my super long security Key 123"))
                    };
                });

            services.AddDbContext<JWT_AuthContext>(option => option.UseSqlServer(Configuration.GetConnectionString("JWT_AuthContextConnection")));

        }

IdentityHostingStartup.cs: IdentityHostingStartup.cs:

public class IdentityHostingStartup : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            builder.ConfigureServices((context, services) => {
                services.AddDbContext<JWT_AuthContext>(options =>
                    options.UseSqlServer(
                        context.Configuration.GetConnectionString("JWT_AuthContextConnection")));

                services.AddDefaultIdentity<JWT_AuthUser>()
                    .AddRoles<JWT_AuthRole>()
                    .AddEntityFrameworkStores<JWT_AuthContext>();
            });
        }
    }

Controller Action for JWT generation (Controller A in the previous context): 用于生成JWT的控制器操作(在先前的上下文中为控制器A):

[Route("api/[controller]")]
    [ApiController]
    public class AuthController : ControllerBase
    {
        private UserManager<JWT_AuthUser> _userManager;
        public AuthController(UserManager<JWT_AuthUser> userManager)
        {
            _userManager = userManager;
        }

        [HttpPost("token")]
        public async Task<ActionResult> GetToken()
        {
            var header = Request.Headers["Authorization"];
            if(header.ToString().StartsWith("Basic"))
            {
                var loginInfo = header.ToString().Substring("Basic ".Length).Trim();
                var userNameAndPassword = Encoding.UTF8.GetString(Convert.FromBase64String(loginInfo)); //username:password
                var userName = userNameAndPassword.Split(":")[0];
                var password = userNameAndPassword.Split(":")[1];
                var user = await _userManager.FindByNameAsync(userName);

                if (user != null && await _userManager.CheckPasswordAsync(user,password))
                {
                    //security key
                    string securityKey = "This is my super long security Key 123";

                    //symmetric security key
                    var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey));

                    //signing credentials
                    var signingCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256Signature);

                    //add claims
                    var claims = new List<Claim>();

                    //create token
                    var token = new JwtSecurityToken(
                        issuer: "issuer",
                        audience: "audience",
                        expires: DateTime.Now.AddHours(1),
                        claims: claims,
                        signingCredentials: signingCredentials
                        );

                    //return token
                    return Ok(new JwtSecurityTokenHandler().WriteToken(token));
                }

            }

            return Unauthorized();
}

Controller method for getting user info (Controller B in the previous context): 获取用户信息的控制器方法(在先前的上下文中为控制器B):

[Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {

        private UserManager<JWT_AuthUser> _userManager;
        public ValuesController(UserManager<JWT_AuthUser> userManager)
        {
            _userManager = userManager;
        }

        // GET api/values
        [HttpGet]
        public async Task<ActionResult> Get()
        {
            var user = await _userManager.GetUserAsync(HttpContext.User);
            var role = await _userManager.GetRolesAsync(user);
            return Ok(user);
        }
}

Edit 2: Startup.cs Configure 编辑2:Startup.cs配置

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // 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.UseAuthentication();
            app.UseMvc();
        }

The reason is that you're using UserManager<JWT_AuthUser>.GetUserAsync(user) to get the principal, which belongs to the Identity Authentication Scheme. 原因是您正在使用UserManager<JWT_AuthUser>.GetUserAsync(user)来获取主体,该主体属于Identity验证方案。 As the document describes, this method will only read the IdentityOptions.ClaimsIdentity.UserIdClaimType claim: 如文档所述,此方法将仅读取IdentityOptions.ClaimsIdentity.UserIdClaimType声明:

Returns the user corresponding to the IdentityOptions.ClaimsIdentity.UserIdClaimType claim in the principal or null. 返回与主体中的IdentityOptions.ClaimsIdentity.UserIdClaimType声明对应的用户,或者为null。

Note the claims issued by your GetToken() method is an empty list : 请注意,您的GetToken()方法发出的claims一个空列表

[HttpPost("token")]
public async Task<ActionResult> GetToken()
{
    ....
        //add claims
        var claims = new List<Claim>();

        //create token
        var token = new JwtSecurityToken(
            issuer: "issuer",
            audience: "audience",
            expires: DateTime.Now.AddHours(1),
            claims: claims,
            signingCredentials: signingCredentials
            );
   ....

}

Since there's no such a IdentityOptions.ClaimsIdentity.UserIdClaimType claim , you'll get a null when invoking var user = await _userManager.GetUserAsync(HttpContext.User); 由于没有这样的IdentityOptions.ClaimsIdentity.UserIdClaimType声明 ,因此在调用var user = await _userManager.GetUserAsync(HttpContext.User);时,您将获得null var user = await _userManager.GetUserAsync(HttpContext.User); .

And because the user is null , it throws when invoking await _userManager.GetRolesAsync(user); 并且由于user为null ,因此在调用await _userManager.GetRolesAsync(user);时抛出该异常await _userManager.GetRolesAsync(user);

How to Fix 怎么修

  1. Inject the IdentityOptions to get the UserIdClaimType : 注入IdentityOptions以获取UserIdClaimType
    [Route("api/[controller]")]
    [ApiController]
    public class AuthController : ControllerBase
    {
        private UserManager<IdentityUser> _userManager;
        private readonly IdentityOptions _idOpts;

        public AuthController(UserManager<IdentityUser> userManager,IOptions<IdentityOptions> optionsAccessor)
        {
            _userManager = userManager;
            this._idOpts = optionsAccessor.Value?? new IdentityOptions();
        }

  1. Add claims before sending the token: 在发送令牌之前添加声明:
//add claims
    var claims = new List<Claim>();
    claims.Add(new Claim(this._idOpts.ClaimsIdentity.UserIdClaimType, user.Id ));

    //create token
    var token = new JwtSecurityToken(
        issuer: "issuer",
        audience: "audience",
        expires: DateTime.Now.AddHours(1),
        claims: claims,
        signingCredentials: signingCredentials
     );

Another question inspired me enter link description here by the idea of holding user info inside JWT claim. 另一个问题激发了我在JWT声明中保留用户信息的想法,从而在此处输入链接描述

In the JWT generating action method inside Controller A, I use Usermanager to get user information of my credentials and put them into JWT claims. 在控制器A内的JWT生成操作方法中,我使用Usermanager来获取我的凭据的用户信息并将其放入JWT声明中。

var roles = await _userManager.GetRolesAsync(user);
var claims = new List<Claim>();
claims.Add( new Claim("Role", roles[0]));

After passing the JWT to controller B, this piece of code help me get the claim info: 将JWT传递给控制器​​B后,这段代码可帮助我获取索赔信息:

var roleClaim = User.Claims.FirstOrDefault(x => x.Type.Equals("Role", StringComparison.InvariantCultureIgnoreCase));

Which fetch me the role 哪个让我扮演角色

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在使用IdentityServer进行身份验证后获取WebAPI控制器上的用户信息? - How to get user's information on WebAPI controller after authenticated with IdentityServer? 在 cookie 中存储 JWT 令牌后如何打破该 cookie 并在 ASP.NET Core 3.1 中获取信息 - After store JWT token in cookie how to break that cookie and get information in ASP.NET Core 3.1 如何从 jwt 令牌中获取用户 ID? - How to get user id from jwt token? 在联合身份验证authN之后获取用户声明,并将其包含在请求JWT中 - Get user claims after federation authN and include it in requesting a JWT 控制器中没有IPrincipal用户信息 - No IPrincipal user information in controller 添加新声明后如何更改 JWT 令牌 - How to change JWT Token after adding new claim ASP.NET Core3.1登录后如何获取用户信息 - How to get User Information after login in ASP.NET Core3.1 登录后如何获取/显示用户信息。ASP.net C# - How to get/display the user-information after logging in. ASP.net C# "如何以角度自动获取新的 JWT 令牌和刷新令牌" - how to get automatically new JWT Token and Refresh Token in angular 如何通过使用JWT Bearer令牌获取用户声明 - How to get user claims by using JWT Bearer token
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM