Javascript Dotnet core webapi通过JWT身份验证返回401未经授权
我在VS代码中使用HTML/Javascript,并在Visual Studio 2019中使用Dot net core 3.1进行Web API开发。还可以在Windows 10 professional上使用IIS来测试APIJavascript Dotnet core webapi通过JWT身份验证返回401未经授权,javascript,asp.net-core,.net-core,Javascript,Asp.net Core,.net Core,我在VS代码中使用HTML/Javascript,并在Visual Studio 2019中使用Dot net core 3.1进行Web API开发。还可以在Windows 10 professional上使用IIS来测试API 开发了带有以下代码的登录页面。一旦用户输入用户ID和密码,单击登录按钮,就会调用web api“TestAuthService” API TestAuthService在本地主机8091上的IIS中发布。成功登录后,JWT将返回到javascript。这工作正常。JW
[ApiController]
[Route("[controller]")]
[Authorize]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
这个问题现在似乎已经解决了。 已将获取api调用更正为
const response = await fetch(url, {
headers: {
"Authorization": `Bearer ${inMemToken}`
}
});
``
你能分享一下你的auth控制器登录方法吗?我们需要知道您是如何生成令牌的。此外,我建议您可以尝试使用postman来测试生成的令牌是否正确,并可以发送到身份验证api。我在#2中添加了代码,我使用postman来验证生成的令牌,使用jwt.io验证令牌您确保令牌是正确的,并且您可以通过使用该令牌访问web api,对吗?我刚刚使用Postman GET请求进行了测试,并在Postman的Auth部分粘贴了承载令牌。我得到了200个OK的回复,但在邮递员回复正文部分没有看到天气数据。相反,我看到的是实际的weatherinfo.html页面,
public class AuthRepository : IAuthRepository
{
private readonly AppDbContext _context;
private readonly IConfiguration _configuration;
public AuthRepository(AppDbContext context, IConfiguration configuration)
{
_configuration = configuration;
_context = context;
}
public async Task<ServiceResponse<string>> Login(string username, string password)
{
var response = new ServiceResponse<string>();
var user = await _context.Users.FirstOrDefaultAsync(x => x.Username.ToLower().Equals(username.ToLower()));
if (user == null)
{
response.Success = false;
response.Message = "User not found.";
}
else if (!VerifyPasswordHash(password, user.PasswordHash, user.PasswordSalt))
{
response.Success = false;
response.Message = "Wrong password.";
}
else
{
response.Data = CreateToken(user);
}
return response;
}
public async Task<ServiceResponse<User>> Register(User user, string password)
{
ServiceResponse<User> response = new ServiceResponse<User>();
if (await UserExists(user.Username))
{
response.Success = false;
response.Message = "User already exists.";
return response;
}
CreatePasswordHash(password, out byte[] passwordHash, out byte[] passwordSalt);
user.PasswordHash = passwordHash;
user.PasswordSalt = passwordSalt;
_context.Users.Add(user);
await _context.SaveChangesAsync();
response.Data = user;
return response;
}
public async Task<bool> UserExists(string username)
{
if (await _context.Users.AnyAsync(x => x.Username.ToLower().Equals(username.ToLower())))
{
return true;
}
return false;
}
private void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
{
using (var hmac = new System.Security.Cryptography.HMACSHA512())
{
passwordSalt = hmac.Key;
passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
}
}
private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
using (var hmac = new System.Security.Cryptography.HMACSHA512(passwordSalt))
{
var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
for (int i = 0; i < computedHash.Length; i++)
{
if (computedHash[i] != passwordHash[i])
{
return false;
}
}
return true;
}
}
private string CreateToken(User user)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Username)
};
var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_configuration.GetSection("AppSettings:Token").Value));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);
var tokendDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = System.DateTime.Now.AddDays(1),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokendDescriptor);
return tokenHandler.WriteToken(token);
}
<button type="button" onclick="return getWeather();">Get Weather data</button>
<table id="weatherdata">
<thead>
</thead>
<tbody id="weatherdatalist">
</tbody>
</table>
<script>
async function getWeather() {
const url = 'http://localhost:5861/weatherforecast';
const localstorage_user = JSON.parse(localStorage.getItem('user'));
const inMemToken = localstorage_user.data
console.log(inMemToken)
/*
const response = await fetch(url);
*/
const response = await fetch(url, {
headers: {
Authorization: 'Bearer ${inMemToken}'
}
});
const data = await response.json();
console.log(data)
display(data);
}
function display(data) {
let tab = "";
data.forEach(element => {
tab += `<tr>
<td > ${element.date} </td>
<td> ${element.temperatureC} </td>
<td> ${element.temperatureF} </td>
<td> ${element.summary} </td>
</tr>`;
});
document.getElementById("weatherdatalist").innerHTML = tab;
}
</script>
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(o => o.AddPolicy("AllowOrigins", builder =>
{
builder.WithOrigins("http://localhost:5500", "http://127.0.0.1:5500")
.AllowAnyMethod()
.AllowAnyHeader();
}));
services.AddControllers();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = false,
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();
}
app.UseAuthentication();
app.UseRouting();
app.UseCors("AllowOrigins");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
[ApiController]
[Route("[controller]")]
[Authorize]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
const response = await fetch(url, {
headers: {
Authorization: 'Bearer ${inMemToken}'
}
});
const response = await fetch(url, {
headers: {
"Authorization": `Bearer ${inMemToken}`
}
});
``