Tim*_*thy 18 c# authorization unauthorized asp.net-core-webapi
我有一个 ASP .NET Core web api,我生成了一个用于授权目的的 JWT 令牌,但是每当我使用带有 Bearer 令牌标头的 Postman 发出请求时,我都会得到 401 Unauthorized。当我从使用 API 的前端尝试时也是如此。当我删除授权时一切正常
尝试将标题中的授权更改为
//[Authorize(AuthenticationSchemes = "Bearer")]
也转到 jwt.io 以确保 JWT 令牌有效。
//function where I generate JWT
public User AuthenticateAdmin(string username, string password)
{
var user = _context.User.FirstOrDefault(x => x.UserName == username && x.Password == password);
//return null if user is not found
if (user == null) return null;
//authentication successful so generate jwt token
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.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);
user.Password = null;
return user;
}
Run Code Online (Sandbox Code Playgroud)
//my startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.EntityFrameworkCore;
using TheBackend.Models;
using TheBackend.Helpers;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using System.Text;
using TheBackend.Services;
using Microsoft.AspNetCore.Identity.UI.Services;
using Newtonsoft.Json.Serialization;
using Microsoft.AspNetCore.Authorization;
namespace TheBackend
{
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.Configure<AuthMessengerOptions>(Configuration);
var connection = @"Host=localhost;Database=PayArenaMock;Username=postgres;Password=tim";
services.AddDbContext<PayArenaMockContext>(options => options.UseNpgsql(connection));
services.AddTransient<IEmailSender, EmailSender>();
//services.AddAuthorization(auth =>
//{
// auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
// .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme??)
// .RequireAuthenticatedUser().Build());
//});
services.AddCors();
//services.AddMvcCore()
// .AddAuthorization() // Note - this is on the IMvcBuilder, not the service collection
// .AddJsonFormatters(options => options.ContractResolver = new CamelCasePropertyNamesContractResolver());
//services.AddMvcCore().AddJsonFormatters(options => options.ContractResolver = new CamelCasePropertyNamesContractResolver());
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
//configure strongly typed settings objects
var appSettingsSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection);
//configure JWT authentication
var appSettings = appSettingsSection.Get<AppSettings>();
var key = Encoding.ASCII.GetBytes(appSettings.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
};
});
services.AddScoped<IUserService, UserService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
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.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseAuthentication();
app.UseHttpsRedirection();
app.UseMvc();
}
}
}
Run Code Online (Sandbox Code Playgroud)
//controller
//[Authorize(AuthenticationSchemes = "Bearer")]
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class BusinessListingsController : ControllerBase
{
private readonly PayArenaMockContext _context;
public BusinessListingsController(PayArenaMockContext context)
{
_context = context;
}
// GET: api/BusinessListings
[HttpGet]
//[AllowAnonymous]
//[Authorize(Roles = Role.Admin)]
public async Task<ActionResult<IEnumerable<BusinessListing>>> GetBusinessListing()
{
//var businesslisting = _context.BusinessListing.Include(b => b.CategoryNameNav);
var businesslisting = await _context.BusinessListing.ToListAsync()
;
return Ok( businesslisting);
}
Run Code Online (Sandbox Code Playgroud)
tle*_*tle 32
我有同样的问题,但在移动之后
app.UseAuthentication();
Run Code Online (Sandbox Code Playgroud)
到前线
app.UseAuthorization();
Run Code Online (Sandbox Code Playgroud)
在
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
..
app.UseAuthentication();
..
app.UseAuthorization();
...
}
Run Code Online (Sandbox Code Playgroud)
有效。
jam*_*tap 19
我在 dotnet core 3.1 上遇到了这个问题,我正在翻转每个开关试图让它工作。最终让这个运行起来的是 tletle 的答案。app.UseAuthentication()
之前执行app.UseAuthorization()
。为了详细说明tletle的答案,以下是相关代码。
在Startup.cs
:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// ...
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication(); // this one first
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
Run Code Online (Sandbox Code Playgroud)
我的身份验证中间件位于我编写的扩展方法中,该ConfigureServices()
方法是从 中的方法调用的Startup.cs
:
public static void ConfigureAuthentication(this IServiceCollection services, IConfiguration configuration)
{
string issuer = configuration.GetValue<string>("Jwt:Issuer");
string signingKey = configuration.GetValue<string>("Jwt:Key");
byte[] signingKeyBytes = System.Text.Encoding.UTF8.GetBytes(signingKey);
services.AddAuthentication(opt=>
{
opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options=>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidIssuer = issuer,
ValidateAudience = true,
ValidAudience = issuer,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ClockSkew = System.TimeSpan.Zero,
IssuerSigningKey = new SymmetricSecurityKey(signingKeyBytes)
};
});
}
Run Code Online (Sandbox Code Playgroud)
并且令牌是使用此扩展方法生成的:
public static string GenerateApiUserToken(this ApiUser user, IConfiguration configuration)
{
string signingKey = configuration.GetValue<string>("Jwt:Key");
string issuer = configuration.GetValue<string>("Jwt:Issuer");
int hours = configuration.GetValue<int>("Jwt:HoursValid");
System.DateTime expireDateTime = System.DateTime.UtcNow.AddHours(hours);
byte[] signingKeyBytes = System.Text.Encoding.UTF8.GetBytes(signingKey);
SymmetricSecurityKey secKey = new SymmetricSecurityKey(signingKeyBytes);
SigningCredentials creds = new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256);
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Role, user.RoleName)
};
JwtSecurityToken token = new JwtSecurityToken(
issuer:issuer,
audience: issuer,
claims: authClaims,
expires: System.DateTime.UtcNow.AddHours(hours),
signingCredentials:creds
);
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
string writtenToken = handler.WriteToken(token);
return writtenToken;
}
Run Code Online (Sandbox Code Playgroud)
我的控制器类:
[Authorize]
[ApiController]
[Microsoft.AspNetCore.Mvc.Produces("application/json")]
[Microsoft.AspNetCore.Mvc.Route("/[controller]/values", Name="MyController")]
public class MyController : Microsoft.AspNetCore.Mvc.Controller
Run Code Online (Sandbox Code Playgroud)
如果[Authorize]
标签在控制器上,你应该删除成员方法上的任何标签;我在我正在测试的方法上留下了一个,直到我删除它,修复程序才会起作用。
小智 6
从 HTTP 切换到 HTTPS 后,我遇到了同样的问题。它在使用 HTTP 的 POSTMAN 中运行良好,但是当我切换到 HTTPS 时,它开始返回401 未经授权
我一添加问题就解决了
app.UseAuthentication();
Run Code Online (Sandbox Code Playgroud)
里面
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
}
Run Code Online (Sandbox Code Playgroud)
内
public class Startup
{
}
Run Code Online (Sandbox Code Playgroud)
它终于起作用了,不是 100% 确定为什么,但我headers: { Authorization: "Bearer" + " " + Bearer }
在我的 React 应用程序中做到了。我在 Postman 中做了同样的事情,但它不起作用。
归档时间: |
|
查看次数: |
21257 次 |
最近记录: |