我正在尝试尽可能简单地在asp.net核心webAPI上实现JWT身份验证。 我不知道我缺少什么,但是即使使用 proper 承载令牌,它也总是返回401。
这是我的configureServices代码
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(
x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("A_VERY_SECRET_SECURITY_KEY_FOR_JWT_AUTH")),
ValidateAudience = false,
ValidateIssuer = false,
};
}
);
services.AddControllers();
services.AddDbContext<dingdogdbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("dingdogdbContext")));
}
这就是我生成令牌的方式
[AllowAnonymous]
[HttpPost("/Login")]
public ActionResult<User> Login(AuthModel auth)
{
var user = new User();
user.Email = auth.Email;
user.Password = auth.Password;
//var user = await _context.User.SingleOrDefaultAsync(u=> u.Email == auth.Email && u.Password==auth.Password);
//if(user==null) return NotFound("User not found with this creds");
//starting token generation...
var tokenHandler = new JwtSecurityTokenHandler();
var seckey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("A_VERY_SECRET_SECURITY_KEY_FOR_JWT_AUTH"));
var signingCreds = new SigningCredentials(seckey, SecurityAlgorithms.HmacSha256Signature);
var token = tokenHandler.CreateToken(new SecurityTokenDescriptor
{
Subject = new System.Security.Claims.ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, user.Id.ToString()) }),
SigningCredentials = signingCreds,
Expires = DateTime.UtcNow.AddDays(7),
});
user.Token = tokenHandler.WriteToken(token);
return user;
}
然后我在app.useRouting()之后添加了app.useAuthorization()。 当我向/ Login发送POST请求时,我正在获取令牌。但是当我使用令牌在邮递员中查询任何其他终结点时(在邮递员的授权/ JWT中添加了令牌)每次都得到401未经授权。 我还有什么想念的吗?
答案 0 :(得分:5)
请记住,UseAuthentication
,UseRouting
和UseAuthorization
中间件必须正确,以便ASP框架正确地将身份上下文注入到http请求。
它应该像这样:(.NET Core 3.1)
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
答案 1 :(得分:2)
第1步: 首先确保 stratup.cs 类中 configure 方法的顺序:
在下面,我给出了有效的asp.net core 3.1订购表
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
如果第1步不起作用,请尝试第2步: 确保令牌验证参数和令牌生成参数及算法都相同,请转到startup.cs类的ConfigureServices方法,并转到生成了令牌的类或方法(在本例中为UserService类< / p>
ConfigureServices方法代码:
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration.GetConnectionString("mySQLConnectionString");
services.AddDbContext<ApplicationDbContext>(options => options.UseMySql(connectionString));
services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequiredLength = 5;
}).AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
services.AddAuthentication(auth =>
{
auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = Configuration["AuthSettings:Audience"],
ValidIssuer = Configuration["AuthSettings:Issuer"],
RequireExpirationTime = true,
IssuerSigningKey =
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(Configuration["AuthSettings:key"])),
ValidateIssuerSigningKey = true,
};
});
services.AddScoped<IUserService, UserService>();
services.AddControllers();
}
令牌生成代码:
public async Task<UserManagerResponse> LoginUserAsync(LoginVIewModel model)
{
var user = await _userManager.FindByEmailAsync(model.Email);
if(user == null)
{
return new UserManagerResponse
{
Message = "There is no user with that email",
iSSuccess= false
};
}
var result = await _userManager.CheckPasswordAsync(user, model.Password);
if(! result)
{
return new UserManagerResponse
{
Message = "Your Provided password not match eith our system ",
iSSuccess = false
};
}
var clims = new[]
{
new Claim("Email", model.Email),
new Claim(ClaimTypes.NameIdentifier, user.Id)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["AuthSettings:key"]));
var token = new JwtSecurityToken(
issuer: _configuration["AuthSettings:Issuer"],
audience: _configuration["AuthSettings:Audience"],
claims: clims,
expires: DateTime.Now.AddDays(30),
signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
);
string tokenAsString = new JwtSecurityTokenHandler().WriteToken(token);
return new UserManagerResponse
{
Message = tokenAsString,
iSSuccess = true,
ExpireDate = token.ValidTo
};
}
}
还请注意,就我而言,我在appsetting.json中有一些拼写错误 例如,在令牌生成代码中,我已将代码称为Audience,但在appSetting.json中则是Audience。那就是为什么两个观众都不匹配的原因。
audience: _configuration["AuthSettings:Audince"]
Appsetting.json代码:
"AllowedHosts": "*",
"AuthSettings": {
"key": "TThis is mfw sec test token",
"Audience": "www.mfw.com",
"Issuer": "www.mfw.com"
}
答案 2 :(得分:0)
首先,您需要检查使用configureServices代码生成的JWT令牌是否有效。要验证JWT令牌,可以使用JWT debugger。它将把JWT令牌值解析为每个参数,通过它们您可以验证哪个参数值分配不正确,并且JWT调试器还为您提供JWT有效或无效。 一旦弄清了这一点,您就可以解决已确定的错误或下一步行动。
答案 3 :(得分:0)