JWT 身份验证始终返回 401 HTTP 错误 asp.net core
Posted
技术标签:
【中文标题】JWT 身份验证始终返回 401 HTTP 错误 asp.net core【英文标题】:JWT authentication always return 401 HTTP Error asp.net core 【发布时间】:2021-10-14 15:16:01 【问题描述】:我每次尝试登录时都会收到相同的错误,即 401 Http 错误。我正在使用 JWT 进行身份验证。
下面是我的启动课:
public class Startup
private readonly IConfiguration _configuration;
public Startup(IConfiguration configuration)
_configuration = configuration;
public void ConfigureServices(IServiceCollection services)
services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(_configuration.GetConnectionString("DBCS")));
services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<DatabaseContext>().AddDefaultTokenProviders();
services.AddSingleton<EmailHelper>();
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddTransient<IProductService, ProductService>();
services.AddTransient<ICustomerService, CustomerService>();
services.AddTransient<ISelectListService, SelectListService>();
services.AddTransient<ITokenService, TokenService>();
services.AddTransient<UserResolverService>();
services.AddAutoMapper(typeof(Startup));
services.AddSession(options =>
options.IdleTimeout = TimeSpan.FromMinutes(180);
);
var secretKey = Encoding.ASCII.GetBytes(_configuration["JWT:key"]);
services.AddAuthentication(options =>
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
)
.AddJwtBearer(jwt =>
var key = Encoding.ASCII.GetBytes(_configuration["JWT:key"]);
jwt.SaveToken = true;
jwt.TokenValidationParameters = new TokenValidationParameters
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
RequireExpirationTime = false,
ValidateLifetime = true
;
);
//Localization
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization(options =>
options.DataAnnotationLocalizerProvider = (type, factory) =>
factory.Create(typeof(SharedResource));
);
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization(options =>
options.DataAnnotationLocalizerProvider = (type, factory) =>
factory.Create(typeof(SharedResource));
);
services.Configure<RequestLocalizationOptions>(options =>
var culture_en = CultureInfo.CreateSpecificCulture("en-US");
//var culture_ar = CultureInfo.CreateSpecificCulture("ar-JO");
var supportedCultures = new[]
culture_en,
//culture_ar,
;
options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.RequestCultureProviders = new[] new RouteDataRequestCultureProvider
IndexOfCulture=1,
IndexofUICulture=1
;
);
services.Configure<RouteOptions>(options =>
options.ConstraintMap.Add("culture", typeof(LanguageRouteConstraint));
);
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
//app.UseExceptionHandler("/Error");
else
app.UseExceptionHandler("/Error");
app.UseHsts();
app.UseStaticFiles();
//app.UseStatusCodePagesWithRedirects("/Error");
app.UseHttpsRedirection();
app.UseSession();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
endpoints.MapControllerRoute(
name: "LocalizedAreas",
pattern: "culture=en/area:exists/controller=Home/action=Index/id?"
);
endpoints.MapControllerRoute(
name: "Areas",
pattern: "area:exists/controller=Home/action=Index/id?"
);
endpoints.MapControllerRoute(
name: "LocalizedDefault",
pattern: "culture=en/controller=Home/action=Index/id?"
);
endpoints.MapControllerRoute(
name: "default",
pattern: "*catchall",
defaults: new controller = "Home", action = "RedirectToDefaultLanguage", culture = "en" );
);
public class LanguageRouteConstraint : IRouteConstraint
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
if (!values.ContainsKey("culture"))
return false;
var culture = values["culture"].ToString();
return culture == "en" || culture == "ar";
下面是我的名为 Account 的控制器,它确保用户存在并相应地生成一个令牌:
[HttpPost, ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginVM model)
var user = await _userManager.FindByNameAsync(model.Email);
if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
var authClaim = new List<Claim>
new Claim("Id", user.CustomerId.ToString()),
new Claim(JwtRegisteredClaimNames.Email, user.Email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
;
var JWTtoken = new JwtSecurityToken(
issuer: _configuration["JWT:issuer"],
audience: _configuration["JWT:audience"],
claims: authClaim.AsEnumerable<Claim>(),
expires: new DateTimeOffset(DateTime.Now.AddMinutes(90)).DateTime,
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_configuration["JWT:key"])), SecurityAlgorithms.HmacSha256)
);
var token = new JwtSecurityTokenHandler().WriteToken(JWTtoken);
if (token != null)
return RedirectToAction("Index", "Profile", new area = "Store" );
else
ModelState.AddModelError("", (string)_localizer["InvalidLogin"]);
return View(model);
ModelState.AddModelError("", (string)_localizer["InvalidLogin"]);
return View(model);
生成令牌后,我将用户重定向到他/她的个人资料,下面是个人资料控制器:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Area("Store")]
public class ProfileController : Controller
[HttpGet]
public IActionResult Index()
return View();
提前感谢您,非常感谢您的帮助。
【问题讨论】:
您的代码没有显示客户端如何检索令牌或服务器如何验证令牌。Login
不会将令牌返回给调用者。您是否正在调试代码,手动复制token
,并将其分配到某个地方进行测试?
正如 Tom W 所说,当您调用另一个授权请求时,您需要将啤酒令牌复制到标头(或任何其他方式)。否则总是返回 401。另外,ValidateIssuer
和 ValidateAudience
设置为 false,所以JWTtoken
不需要添加受众和发布者。
另外,如果你使用mvc,我认为cookie认证是一种更好的方式。 Jwt 令牌认证更适合 web api 项目。
【参考方案1】:
谢谢大家的cmets和帮助,我上网找到了解决问题的办法。我通过在 Startup 类 Configure 方法中添加以下内容来解决它:
app.UseSession();
app.Use(async (context, next) =>
var token = context.Session.GetString("token");
if (!string.IsNullOrEmpty(token))
context.Request.Headers.Add("Authorization", "Bearer " + token);
await next();
);
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints()
【讨论】:
以上是关于JWT 身份验证始终返回 401 HTTP 错误 asp.net core的主要内容,如果未能解决你的问题,请参考以下文章
为啥 OAuth2 身份验证服务器使用 jdbc 数据源返回 401 错误?
Nest.js Auth Guard JWT 身份验证不断返回 401 未授权