Asp.net6 授权。我有能力向客户端发送 JWT,但是当我尝试访问我的端点时,我得到 401。非常困惑
Asp.net 6 Authorization. I have the ability to send the client a JWT but when I try access my end points I get 401. Very Confused
我正在尝试使用在用户登录时发送给用户的 JWT 令牌来解锁我的端点(控制器)。目前注册和登录有效,用户收到了一个 JWT 令牌。但是,当我使用邮递员或我的移动应用程序将 JWT 发送到 API 时,我收到 401 Unauthorized 错误。我正在使用 Asp.net 6 网络 API。我已经添加了我的身份验证控制器和我的 program.cs。我的 appsettings.json 以及发行者和受众中都有我的 JWT 密钥。我确定我的错误在 program.cs
AuthController
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using VelocityNetAPI.Models;
using System.Security.Cryptography;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using VelocityNetAPI.Data;
using Microsoft.AspNetCore.Authorization;
namespace VelocityNetAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
public static User user = new User();
private readonly IConfiguration configuration;
private readonly VelocityNetAPIContext context;
public AuthController(IConfiguration configuration, VelocityNetAPIContext context)
{
this.configuration = configuration;
this.context = context;
}
[HttpPost("Register")]
public async Task<ActionResult<User>> Register(UserDto request)
{
CreatePasswordHash(request.Password, out byte[] passwordHash, out byte[] passwordSalt);
user.Name = request.Username;
user.PasswordHash = passwordHash;
user.PasswordSalt = passwordSalt;
user.Role = "User";
context.User.Add(user);
await context.SaveChangesAsync();
return Ok(user);
}
[HttpPost("Login")]
public async Task<ActionResult<string>> Login(UserDto request)
{
//search for user
var user = context.User.FirstOrDefault(u => u.Name == request.Username);
if (user == null)
{
return BadRequest("User not found");
}
if(!VerifyPasswordHash(request.Password, user.PasswordHash, user.PasswordSalt))
{
return BadRequest("Wrong Password");
}
string token = CreateToken(user);
return Ok(token);
}
private string CreateToken(User user)
{
List<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Name),
new Claim(ClaimTypes.Role, user.Role),
};
var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(configuration["Jwt:key"]));
var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha512);
var token = new JwtSecurityToken(
claims: claims,
expires: DateTime.Now.AddDays(1),
signingCredentials: cred);
var jwt = new JwtSecurityTokenHandler().WriteToken(token);
return jwt;
}
private void CreatePasswordHash(String password, out byte[] passwordHash, out byte[] passwordSalt)
{
using (HMACSHA512 hmac = new HMACSHA512())
{
passwordSalt = hmac.Key;
passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
}
}
private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
using (HMACSHA512 hmac = new HMACSHA512(passwordSalt))
{
var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
return computedHash.SequenceEqual(passwordHash);
}
}
}
}
Program.cs
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using VelocityNetAPI.Data;
using Microsoft.IdentityModel.Tokens;
using System.Configuration;
using Swashbuckle.AspNetCore.SwaggerGen;
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.Authorization;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<VelocityNetAPIContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("VelocityNetAPIContext")));
var conf = builder.Configuration;
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = true;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = conf["Jwt:Issuer"].ToString(),
ValidAudience = conf["Jwt:Audience"].ToString(),
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(conf["Jwt:Key"]))
};
});
//Configuration.GetSection("AppSettings:Token").Value)
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
如果您需要更多信息,请告诉我
大家干杯
您将 ValidateIssuer
和 ValidateAudience
设置为真。但是在您的 CreateToken
方法中,您不使用 Issuer
和 Audience
来生成令牌。
您可以更改 CreateToken
方法,如下所示:
var token = new JwtSecurityToken(configuration["Jwt:Issuer"],
configuration["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddDays(1),
signingCredentials: cred);
我正在尝试使用在用户登录时发送给用户的 JWT 令牌来解锁我的端点(控制器)。目前注册和登录有效,用户收到了一个 JWT 令牌。但是,当我使用邮递员或我的移动应用程序将 JWT 发送到 API 时,我收到 401 Unauthorized 错误。我正在使用 Asp.net 6 网络 API。我已经添加了我的身份验证控制器和我的 program.cs。我的 appsettings.json 以及发行者和受众中都有我的 JWT 密钥。我确定我的错误在 program.cs
AuthController
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using VelocityNetAPI.Models;
using System.Security.Cryptography;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using VelocityNetAPI.Data;
using Microsoft.AspNetCore.Authorization;
namespace VelocityNetAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
public static User user = new User();
private readonly IConfiguration configuration;
private readonly VelocityNetAPIContext context;
public AuthController(IConfiguration configuration, VelocityNetAPIContext context)
{
this.configuration = configuration;
this.context = context;
}
[HttpPost("Register")]
public async Task<ActionResult<User>> Register(UserDto request)
{
CreatePasswordHash(request.Password, out byte[] passwordHash, out byte[] passwordSalt);
user.Name = request.Username;
user.PasswordHash = passwordHash;
user.PasswordSalt = passwordSalt;
user.Role = "User";
context.User.Add(user);
await context.SaveChangesAsync();
return Ok(user);
}
[HttpPost("Login")]
public async Task<ActionResult<string>> Login(UserDto request)
{
//search for user
var user = context.User.FirstOrDefault(u => u.Name == request.Username);
if (user == null)
{
return BadRequest("User not found");
}
if(!VerifyPasswordHash(request.Password, user.PasswordHash, user.PasswordSalt))
{
return BadRequest("Wrong Password");
}
string token = CreateToken(user);
return Ok(token);
}
private string CreateToken(User user)
{
List<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Name),
new Claim(ClaimTypes.Role, user.Role),
};
var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(configuration["Jwt:key"]));
var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha512);
var token = new JwtSecurityToken(
claims: claims,
expires: DateTime.Now.AddDays(1),
signingCredentials: cred);
var jwt = new JwtSecurityTokenHandler().WriteToken(token);
return jwt;
}
private void CreatePasswordHash(String password, out byte[] passwordHash, out byte[] passwordSalt)
{
using (HMACSHA512 hmac = new HMACSHA512())
{
passwordSalt = hmac.Key;
passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
}
}
private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
using (HMACSHA512 hmac = new HMACSHA512(passwordSalt))
{
var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
return computedHash.SequenceEqual(passwordHash);
}
}
}
}
Program.cs
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using VelocityNetAPI.Data;
using Microsoft.IdentityModel.Tokens;
using System.Configuration;
using Swashbuckle.AspNetCore.SwaggerGen;
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.Authorization;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<VelocityNetAPIContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("VelocityNetAPIContext")));
var conf = builder.Configuration;
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = true;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = conf["Jwt:Issuer"].ToString(),
ValidAudience = conf["Jwt:Audience"].ToString(),
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(conf["Jwt:Key"]))
};
});
//Configuration.GetSection("AppSettings:Token").Value)
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
如果您需要更多信息,请告诉我 大家干杯
您将 ValidateIssuer
和 ValidateAudience
设置为真。但是在您的 CreateToken
方法中,您不使用 Issuer
和 Audience
来生成令牌。
您可以更改 CreateToken
方法,如下所示:
var token = new JwtSecurityToken(configuration["Jwt:Issuer"],
configuration["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddDays(1),
signingCredentials: cred);