通过 JQuery Ajax 发送授权令牌承载 - 后端是 .NET Core Web Api
Sending Authorization Token Bearer through JQuery Ajax - Back end is .NET Core Web Api
当我使用 Jquery Ajax 访问 api 时出现 401
错误代码。
这是我的前端代码:
$(document).ready(function() {
$("#submit").click(function(e) {
debugger
let payLoad = JSON.stringify({
Username: $("#username").val(),
Password: $("#password").val()
});
console.log(payLoad)
$.ajax({
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
type: "POST",
url: "https://localhost:44342/api/Authenticate/login",
data: payLoad,
dataType: "json",
success: function(result) {
console.log('ok')
debugger
if (result != "Error") {
console.log('Authenticated');
CallAPI(result);
} else {
console.log('Invalid username or password');
}
},
error: function(req, status, error) {
debugger
alert(error);
}
});
});
function CallAPI(token) {
debugger
$.ajax({
url: 'https://localhost:44342/api/Customers',
headers: {
Authorization: 'Bearer ' + token
},
contentType: "application/json",
dataType: 'json',
success: function(result) {
console.log(result)
},
error: function(error) {
console.log(error);
}
})
}
对于我的后端,我使用 ASP.NET Identity
[HttpPost]
[Route("login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var user = await userManager.FindByNameAsync(model.Username);
if (user != null && await userManager.CheckPasswordAsync(user, model.Password))
{
var userRoles = await userManager.GetRolesAsync(user);
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
foreach (var userRole in userRoles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
}
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var token = new JwtSecurityToken(
issuer: _configuration["JWT:ValidIssuer"],
audience: _configuration["JWT:ValidAudience"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
return Unauthorized();
}
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class CustomersController : ControllerBase
{
private readonly ApplicationContext _context;
public CustomersController(ApplicationContext context)
{
_context = context;
}
// GET: api/Customers
[HttpGet]
public async Task<ActionResult<IEnumerable<Customer>>> GetCustomer()
{
return await _context.Customer.ToListAsync();
}
}
我的 startup.cs 代码是
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();
// For Identity
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Adding Authentication
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
// Adding Jwt Bearer
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = Configuration["JWT:ValidAudience"],
ValidIssuer = Configuration["JWT:ValidIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Secret"]))
};
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
我已经测试过了。没有 [Authorize]
属性,我可以在客户端看到结果响应。但是一旦我添加了 [Authorize]
属性并在 CallAPI
方法中添加了 headers
属性,它就会命中 401
。我已经测试了 https://localhost:44342/api/Authenticate/login
并且它按预期工作。它 returns 令牌。但是当我使用令牌调用 'https://localhost:44342/api/Customers' 时,它命中 401
But once I have added [Authorize] attribute and added headers property in CallAPI method, it hits 401.
根据您分享的Startup.cs
代码,我们发现您在项目中配置了多种认证机制。
正如我们在评论中讨论的那样,我们可以使用它们依赖于对用户进行身份验证的 [Authorize]
属性指定身份验证方案(或方案)。
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
有关选择具有 Authorize 属性的方案的更多信息,请查看此文档:
当我使用 Jquery Ajax 访问 api 时出现 401
错误代码。
这是我的前端代码:
$(document).ready(function() {
$("#submit").click(function(e) {
debugger
let payLoad = JSON.stringify({
Username: $("#username").val(),
Password: $("#password").val()
});
console.log(payLoad)
$.ajax({
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
type: "POST",
url: "https://localhost:44342/api/Authenticate/login",
data: payLoad,
dataType: "json",
success: function(result) {
console.log('ok')
debugger
if (result != "Error") {
console.log('Authenticated');
CallAPI(result);
} else {
console.log('Invalid username or password');
}
},
error: function(req, status, error) {
debugger
alert(error);
}
});
});
function CallAPI(token) {
debugger
$.ajax({
url: 'https://localhost:44342/api/Customers',
headers: {
Authorization: 'Bearer ' + token
},
contentType: "application/json",
dataType: 'json',
success: function(result) {
console.log(result)
},
error: function(error) {
console.log(error);
}
})
}
对于我的后端,我使用 ASP.NET Identity
[HttpPost]
[Route("login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var user = await userManager.FindByNameAsync(model.Username);
if (user != null && await userManager.CheckPasswordAsync(user, model.Password))
{
var userRoles = await userManager.GetRolesAsync(user);
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
foreach (var userRole in userRoles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
}
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var token = new JwtSecurityToken(
issuer: _configuration["JWT:ValidIssuer"],
audience: _configuration["JWT:ValidAudience"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
return Unauthorized();
}
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class CustomersController : ControllerBase
{
private readonly ApplicationContext _context;
public CustomersController(ApplicationContext context)
{
_context = context;
}
// GET: api/Customers
[HttpGet]
public async Task<ActionResult<IEnumerable<Customer>>> GetCustomer()
{
return await _context.Customer.ToListAsync();
}
}
我的 startup.cs 代码是
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();
// For Identity
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Adding Authentication
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
// Adding Jwt Bearer
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = Configuration["JWT:ValidAudience"],
ValidIssuer = Configuration["JWT:ValidIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Secret"]))
};
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
我已经测试过了。没有 [Authorize]
属性,我可以在客户端看到结果响应。但是一旦我添加了 [Authorize]
属性并在 CallAPI
方法中添加了 headers
属性,它就会命中 401
。我已经测试了 https://localhost:44342/api/Authenticate/login
并且它按预期工作。它 returns 令牌。但是当我使用令牌调用 'https://localhost:44342/api/Customers' 时,它命中 401
But once I have added [Authorize] attribute and added headers property in CallAPI method, it hits 401.
根据您分享的Startup.cs
代码,我们发现您在项目中配置了多种认证机制。
正如我们在评论中讨论的那样,我们可以使用它们依赖于对用户进行身份验证的 [Authorize]
属性指定身份验证方案(或方案)。
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
有关选择具有 Authorize 属性的方案的更多信息,请查看此文档: