JWT不记名令牌授权不起作用asp net core web api
Posted
技术标签:
【中文标题】JWT不记名令牌授权不起作用asp net core web api【英文标题】:JWT bearer token Authorization not working asp net core web api 【发布时间】:2020-05-14 05:44:41 【问题描述】:我创建了一个 Web api,它使用 JWT 令牌通过基于角色的策略进行授权(基于 this 文章)。 用户登录会生成一个用于授权的令牌。我成功生成了令牌,但是当我开始使用它来访问受限制的 API 操作时,它不起作用并不断给我 401 HTTP 错误(考虑到操作调用没有触发,我什至无法调试)。我做错了什么?
类:
public class Startup
public Startup(IConfiguration configuration)
Configuration = configuration;
public IConfiguration Configuration get;
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
services.AddControllers();
services.AddScoped<ICountriesService, CountriesService>();
services.AddScoped<ICompanyService, CompanyService>();
services.AddScoped<IPlaneServices, PlaneService>();
services.AddScoped<IPlaneTypeService, PlaneTypeService>();
services.AddScoped<ICitiesService, CitiesService>();
services.AddScoped<IAirfieldService, AirfieldService>();
services.AddScoped<ITicketTypeService, TicketTypeService>();
services.AddScoped<IFlightService, FlightService>();
services.AddScoped<ILuxuryService, LuxuryService>();
services.AddScoped<IUserService, UserService>();
// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo Title = "My API", Version = "v1" );
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
Description = @"JWT Authorization header using the Bearer scheme. \r\n\r\n
Enter 'Bearer' [space] and then your token in the text input below.
\r\n\r\nExample: 'Bearer 12345abcdef'",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
);
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
new OpenApiSecurityScheme
Reference = new OpenApiReference
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
,
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
,
new List<string>()
);
// var xmlFile = $"Assembly.GetExecutingAssembly().GetName().Name.xml";
//var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
//c.IncludeXmlComments(xmlPath);
);
services.AddAutoMapper(cfg => cfg.AddProfile<Mapper.Mapper>(),
AppDomain.CurrentDomain.GetAssemblies());
services.AddDbContext<FlightMasterContext>();
services.AddCors();
var secret = Configuration.GetValue<string>(
"AppSettings:Secret");
var key = Encoding.ASCII.GetBytes(secret);
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(key),
ValidateIssuer = false,
ValidateAudience = false
;
);
// 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();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
// Enable middleware to serve swagger-ui (html, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
c.RoutePrefix = string.Empty;
);
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
// global cors policy
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseEndpoints(endpoints =>
endpoints.MapControllers();
);
控制器:
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class AaTestController : ControllerBase
private FlightMasterContext db get; set;
private IUserService _userService;
public AaTestController(FlightMasterContext db, IUserService userService)
this.db = db;
_userService = userService;
[AllowAnonymous]
[HttpPost("authenticate")]
public IActionResult Authenticate([FromBody]AuthenticateModel model)
var user = _userService.Authenticate(model.Username, model.Password);
if (user == null)
return BadRequest(new message = "Username or password is incorrect" );
return Ok(user);
//DOESNT TRIGGER
[Authorize(Roles = Role.Admin)]
[HttpGet]
public IActionResult GetAll()
var users = _userService.GetAll();
return Ok(users);
[HttpGet("id")]
public IActionResult GetById(int id)
// only allow admins to access other user records
var currentUserId = int.Parse(User.Identity.Name);
if (id != currentUserId && !User.IsInRole(Role.Admin))
return Forbid();
var user = _userService.GetById(id);
if (user == null)
return NotFound();
return Ok(user);
用于身份验证和授权的服务:
public interface IUserService
User Authenticate(string username, string password);
IEnumerable<User> GetAll();
User GetById(int id);
public class UserService : IUserService
// users hardcoded for simplicity, store in a db with hashed passwords in production applications
private List<User> _users = new List<User>
new User Id = 1, FirstName = "Admin", LastName = "User", Username = "admin", Password = "admin", Role = Role.Admin ,
new User Id = 2, FirstName = "Normal", LastName = "User", Username = "user", Password = "user", Role = Role.User
;
public User Authenticate(string username, string password)
var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password);
var secret = "THIS IS Ughjgjhgjhghgighiizgzigiz";
// return null if user not found
if (user == null)
return null;
// authentication successful so generate jwt token
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(secret);
var tokenDescriptor = new SecurityTokenDescriptor
Subject = new ClaimsIdentity(new Claim[]
new Claim(ClaimTypes.Name, user.Id.ToString()),
new Claim(ClaimTypes.Role, user.Role)
),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
;
var token = tokenHandler.CreateToken(tokenDescriptor);
user.Token = tokenHandler.WriteToken(token);
return user.WithoutPassword();
public IEnumerable<User> GetAll()
return _users.WithoutPasswords();
public User GetById(int id)
var user = _users.FirstOrDefault(x => x.Id == id);
return user.WithoutPassword();
【问题讨论】:
【参考方案1】:第一个中间件应该对用户进行身份验证,然后才是下一个 - 授权。不幸的是,并不是所有的 MS 文档都关注这个细节。
【讨论】:
您不应将另一个答案的副本作为答案本身发布。【参考方案2】:这些方法应该以相反的顺序调用:
app.UseAuthentication();
app.UseAuthorization();
第一个中间件应该对用户进行身份验证,然后才是下一个 - 授权。不幸的是,并不是所有的 MS 文档都关注这个细节。
【讨论】:
感谢十亿 谢谢googol 在这个序列上浪费了整整一个小时以上是关于JWT不记名令牌授权不起作用asp net core web api的主要内容,如果未能解决你的问题,请参考以下文章
JWT 不记名令牌授权应用于 .NET Core 中的现有 MVC Web 应用程序
ASP.NET Core API 使用 JWT 不记名令牌进行身份验证
JWT 不记名令牌不适用于 ASP.Net Core 3.1 + Identity Server 4