使用 JWT 令牌授权仍然返回未授权
Authorize using JWT token still returning unauthorized
我的startup.cs(asp.net核心5.0)
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddAuthentication (options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = "https://www.yogihosting.com",
ValidIssuer = "https://www.yogihosting.com",
ClockSkew = TimeSpan.Zero,// It forces tokens to expire exactly at token expiration time instead of 5 minutes later
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"))
};
});
}
我正在尝试调用 http://localhost:31254/Reservation
我想从 CallAPIController.cs
调用的航班预订列表列表 returns
ReservationController.cs
[Authorize]
public IEnumerable<Reservation> Index()
{
return CreateDummyReservations();
}
[HttpGet]
public IEnumerable<Reservation> Get() => CreateDummyReservations();
public List<Reservation> CreateDummyReservations()
{
List<Reservation> rList = new List<Reservation> {
new Reservation { Id=1, Name = "Ankit", StartLocation = "New York", EndLocation="Beijing" },
new Reservation { Id=2, Name = "Bobby", StartLocation = "New Jersey", EndLocation="Boston" },
new Reservation { Id=3, Name = "Jacky", StartLocation = "London", EndLocation="Paris" }
};
return rList;
}
CallAPIController.cs
//entry point of the controller
public async Task<IActionResult> Index(string message)
{
ViewBag.Message = message;
var accessToken = GenerateJSONWebToken(); //generating the token
SetJWTCookie(accessToken); //setting the cookie
List<Reservation> list = await FlightReservation();
return RedirectToAction("Home");
}
private string GenerateJSONWebToken()
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "https://www.yogihosting.com",
audience: "https://www.yogihosting.com",
expires: DateTime.Now.AddHours(3),
signingCredentials: credentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
private void SetJWTCookie(string token)
{
var cookieOptions = new CookieOptions
{
HttpOnly = true,
Expires = DateTime.UtcNow.AddHours(3),
};
Response.Cookies.Append("jwtCookie", token, cookieOptions);
}
public async Task<List<Reservation>> FlightReservation()
{
var jwt = Request.Cookies["jwtCookie"];
List<Reservation> reservationList = new List<Reservation>();
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwt);
//calling the reservation controller asynchronously but returning
unauthorised.
using (var response = await httpClient.GetAsync("http://localhost:31254/Reservation")) // change API URL to yours
{
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string apiResponse = await response.Content.ReadAsStringAsync();
reservationList = JsonConvert.DeserializeObject<List<Reservation>>(apiResponse);
}
if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
//return RedirectToAction("Index", new { message = "Please Login again" });
}
}
}
return reservationList;
}
不过,当我调用预订控制器时,我收到 401 未经授权的错误。如果我删除授权属性,它就可以工作。关键是它没有识别 JWT 令牌或正确验证它。我错过了什么吗?
您的问题出在这一行:
SetJWTCookie(accessToken);
List<Reservation> list = await FlightReservation();
当你设置cookie时,必须在浏览器中收到响应才能在浏览器中设置cookie,以便在后续请求中发送,但响应尚未发送到浏览器,你调用此方法
await FlightReservation();
该方法请求的cookie还没有在浏览器中设置,也没有发送给本次请求,所以这里收到的token为空
var jwt = Request.Cookies["jwtCookie"]; //cookie is null
并且未授权的错误returns,但是如果本次请求结束,后续的请求不会有问题,因为浏览器中设置了cookie。因此,对于您的代码,它将始终 return 在第一个请求中未授权。
但是如果所有请求都失败了,看看你有没有设置UseAuthentication中间件
app.UseRouting();
app.UseAuthentication(); //here
app.UseAuthorization();
您在 SetJWTCookie(string token) 方法中设置了 cookie:
Response.Cookies.Append("jwtCookie", token, cookieOptions)
并且您尝试在 FlightReservation() 方法中获取 cookie:
var jwt = Request.Cookies["jwtCookie"];
您的请求不包含 jwtCookie。所以你无法获得你的智威汤逊的价值
代币
试试下面的方法:
[HttpPost]
public async Task<IActionResult> Authenticate(UserModel someuser)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "https://www.yogihosting.com",
audience: "https://www.yogihosting.com",
expires: DateTime.Now.AddHours(3),
signingCredentials: credentials
);
string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
var response = await httpClient.GetAsync(url); // change API URL to yours
}
return Content(jwtToken);
}
结果:
我的startup.cs(asp.net核心5.0)
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddAuthentication (options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = "https://www.yogihosting.com",
ValidIssuer = "https://www.yogihosting.com",
ClockSkew = TimeSpan.Zero,// It forces tokens to expire exactly at token expiration time instead of 5 minutes later
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"))
};
});
}
我正在尝试调用 http://localhost:31254/Reservation
我想从 CallAPIController.cs
ReservationController.cs
[Authorize]
public IEnumerable<Reservation> Index()
{
return CreateDummyReservations();
}
[HttpGet]
public IEnumerable<Reservation> Get() => CreateDummyReservations();
public List<Reservation> CreateDummyReservations()
{
List<Reservation> rList = new List<Reservation> {
new Reservation { Id=1, Name = "Ankit", StartLocation = "New York", EndLocation="Beijing" },
new Reservation { Id=2, Name = "Bobby", StartLocation = "New Jersey", EndLocation="Boston" },
new Reservation { Id=3, Name = "Jacky", StartLocation = "London", EndLocation="Paris" }
};
return rList;
}
CallAPIController.cs
//entry point of the controller
public async Task<IActionResult> Index(string message)
{
ViewBag.Message = message;
var accessToken = GenerateJSONWebToken(); //generating the token
SetJWTCookie(accessToken); //setting the cookie
List<Reservation> list = await FlightReservation();
return RedirectToAction("Home");
}
private string GenerateJSONWebToken()
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "https://www.yogihosting.com",
audience: "https://www.yogihosting.com",
expires: DateTime.Now.AddHours(3),
signingCredentials: credentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
private void SetJWTCookie(string token)
{
var cookieOptions = new CookieOptions
{
HttpOnly = true,
Expires = DateTime.UtcNow.AddHours(3),
};
Response.Cookies.Append("jwtCookie", token, cookieOptions);
}
public async Task<List<Reservation>> FlightReservation()
{
var jwt = Request.Cookies["jwtCookie"];
List<Reservation> reservationList = new List<Reservation>();
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwt);
//calling the reservation controller asynchronously but returning
unauthorised.
using (var response = await httpClient.GetAsync("http://localhost:31254/Reservation")) // change API URL to yours
{
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string apiResponse = await response.Content.ReadAsStringAsync();
reservationList = JsonConvert.DeserializeObject<List<Reservation>>(apiResponse);
}
if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
//return RedirectToAction("Index", new { message = "Please Login again" });
}
}
}
return reservationList;
}
不过,当我调用预订控制器时,我收到 401 未经授权的错误。如果我删除授权属性,它就可以工作。关键是它没有识别 JWT 令牌或正确验证它。我错过了什么吗?
您的问题出在这一行:
SetJWTCookie(accessToken);
List<Reservation> list = await FlightReservation();
当你设置cookie时,必须在浏览器中收到响应才能在浏览器中设置cookie,以便在后续请求中发送,但响应尚未发送到浏览器,你调用此方法
await FlightReservation();
该方法请求的cookie还没有在浏览器中设置,也没有发送给本次请求,所以这里收到的token为空
var jwt = Request.Cookies["jwtCookie"]; //cookie is null
并且未授权的错误returns,但是如果本次请求结束,后续的请求不会有问题,因为浏览器中设置了cookie。因此,对于您的代码,它将始终 return 在第一个请求中未授权。
但是如果所有请求都失败了,看看你有没有设置UseAuthentication中间件
app.UseRouting();
app.UseAuthentication(); //here
app.UseAuthorization();
您在 SetJWTCookie(string token) 方法中设置了 cookie:
Response.Cookies.Append("jwtCookie", token, cookieOptions)
并且您尝试在 FlightReservation() 方法中获取 cookie:
var jwt = Request.Cookies["jwtCookie"];
您的请求不包含 jwtCookie。所以你无法获得你的智威汤逊的价值 代币
试试下面的方法:
[HttpPost]
public async Task<IActionResult> Authenticate(UserModel someuser)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "https://www.yogihosting.com",
audience: "https://www.yogihosting.com",
expires: DateTime.Now.AddHours(3),
signingCredentials: credentials
);
string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
var response = await httpClient.GetAsync(url); // change API URL to yours
}
return Content(jwtToken);
}
结果: