我在 VS Code 中使用 HTML/Javascript,并在 Visual Studio 2019 中使用 Dot net core 3.1 进行 Web API 开发。同样在 Windows 10 专业版上使用 IIS 来测试 API。
function fnlogin() {
const uname = document.getElementById('uname').value;
const pwd = document.getElementById('pwd').value;
const logindata = {
username: uname,
password: pwd
}
const loginurl = 'http://localhost:8091/api/Auth/Login';
authenticate(loginurl, logindata);
}
async function authenticate(loginurl, logindata) {
console.log(logindata)
const response = await fetch(loginurl , {
method: "POST",
mode: "cors",
body: JSON.stringify(logindata),
headers: { "Content-type" : "application/json, charset=UTF-8"}
});
const rdata = await response.json();
console.log(rdata);
if (!rdata.success) {
document.getElementById("loginMessage").innerHTML = rdata.message;
return;
}
const inMemoryToken = rdata.data
localStorage.setItem('user', JSON.stringify(rdata));
window.location.href = "http://127.0.0.1:5500/Weatherinfo.html";
}
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly IAuthRepository _authRepo;
public AuthController(IAuthRepository authRepo)
{
_authRepo = authRepo;
}
[HttpPost("Register")]
public async Task<ActionResult<ServiceResponse<int>>> Register(UserRegisterDto request)
{
var response = await _authRepo.Register(
new User { Username = request.Username }, request.Password
);
if (!response.Success)
{
return BadRequest(response);
}
return Ok(response);
}
[HttpPost("Login")]
public async Task<ActionResult<ServiceResponse<string>>> Login(UserLoginDto request)
{
var response = await _authRepo.Login(
request.Username, request.Password
);
if (!response.Success)
{
return BadRequest(response);
}
return Ok(response);
}
AuthRepository 代码如下:
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();
}
我不确定我是否在下面的代码中正确传递了 JWT
const response = await fetch(url, {
headers: {
Authorization: 'Bearer ${inMemToken}'
}
});
答案 0 :(得分:0)
问题现在似乎已解决。 将 fetch api 调用更正为
const response = await fetch(url, {
headers: {
"Authorization": `Bearer ${inMemToken}`
}
});
``