简体   繁体   English

使用 Jwt 的基于令牌的身份验证无法授权

[英]Token based authentication with Jwt fails to authorize

I'm trying to set up token-based authentication for my web-api.我正在尝试为我的 web-api 设置基于令牌的身份验证。 As of now i am generating the token correctly, but i'm having issues authorizing with the token.截至目前,我正在正确生成令牌,但我在使用令牌进行授权时遇到问题。 Using postman, i'm getting 401 Unauthorized on all posts.使用 postman,我在所有帖子上都收到 401 Unauthorized。 I have currently configured Jwt as follow:我目前已配置 Jwt 如下:

Startup.cs启动.cs

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        private IConfiguration Configuration { get; }
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey =
                            new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
                    };
                });
            
            
            services.AddMvc();
            services.AddControllers();
            services.AddSingleton<ITitleDataService, TitleDataService>();
            services.AddSingleton<IPersonDataService, PersonDataService>();
            services.AddSingleton<IUserDataService, UserDataService>();
            services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
            services.AddControllersWithViews()
                .AddNewtonsoftJson(options =>
                    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
                );
            services.AddMvc().AddControllersAsServices();
        }

        // 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.UseRequestLogging();
            
            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseFileServer();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

This is my controller:这是我的 controller:

//LOGIN
[HttpPost("user/login/")]
public IActionResult Login(UserDto userDto)
{
    var user = _dataService.Login(userDto.Username, userDto.Password);
    IActionResult response = Unauthorized();
    if (user)
    {
        var tokenStr = GenerateJSONWebToken(userDto);
        response = Ok(new {tokenStr});
    }
    else
    {
        return BadRequest("User not authorized");
    }
    return response;
}

[Authorize]
[HttpPost("post")]
public string Post()
{
    var identity = HttpContext.User.Identity as ClaimsIdentity;
    IList<Claim> claim = identity.Claims.ToList();
    Console.WriteLine(claim.Count);
    var username = claim[0].Value;
    Console.WriteLine(username);
    return "Welcome to " + username;
}

[Authorize]
[HttpGet("GetValue")]
public ActionResult<IEnumerable<string>> Get()
{
    return new string[] {"Value1", "Value2", "Value3"};
}

private string GenerateJSONWebToken(UserDto userDto)
{
    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
    var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
    var claims = new[]
    {
        new Claim(JwtRegisteredClaimNames.Sub, userDto.Username),
        new Claim(JwtRegisteredClaimNames.Email, userDto.Password),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
    };
    
    var token = new JwtSecurityToken(
        issuer: "Issuer",
        audience: "Issuer",
        claims,
        expires: DateTime.Now.AddMinutes(120),
        signingCredentials: credentials);
    
    
    var encodetoken = new JwtSecurityTokenHandler().WriteToken(token);
    return encodetoken;
}

I have tried to rearrange the middleware pipeline without any luck.我试图重新安排中间件管道,但没有任何运气。 I have very little experience with tokens, and am therefore pretty lost on how to solve this.我对令牌的经验很少,因此对如何解决这个问题非常迷茫。 All suggestions are highly appreciated!高度赞赏所有建议!

Best regards, Jesper最好的问候,杰斯珀

You have a couple problems here: You configured your middleware to validate the issuer (URL of the entity that creates the token) and audience (the URL of the service that the token is intended for), but you do not do not specify the values in your configuration.您在这里有几个问题:您将中间件配置为验证颁发者(创建令牌的实体的 URL)和受众(令牌所针对的服务的 URL),但您没有指定值在您的配置中。

Your token is written with issuer and audience as "Issuer", but because your middleware is not configured to accept "Issuer" as the correct value for issuer / audience, your token fails.您的令牌与发行者和受众一起写入“发行者”,但由于您的中间件未配置为接受“发行者”作为发行者/受众的正确值,因此您的令牌失败。

In your middleware, either configure the accepted values for issuer and audience, or bypass issuer and audience validation by setting validateIssuer and validateAudience to false.在您的中间件中,为颁发者和受众配置可接受的值,或者通过将validateIssuervalidateAudience设置为 false 来绕过颁发者和受众验证。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM