我正在使用ASP.NET Core(使用CookieAuthentication
作为我的MVC身份验证和用于Web-API的JWT)制作Web应用程序。
我已经配置了cookie身份验证并成功创建了JWT令牌。但是,我很难授权包含[Authorization(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
属性的API方法。
Startup.cs
services
.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.Name = "CookieAuthentication";
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.ExpireTimeSpan = TimeSpan.FromDays(14);
options.LoginPath = "/Account/Login";
options.LogoutPath = "/Account/Logout";
options.AccessDeniedPath = "/Account/Unauthorized";
});
services
.AddAuthentication()
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:JwtIssuer"],
ValidAudience = Configuration["Jwt:JwtAudience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:JwtSecretKey"]))
};
});
AccountController.cs
[HttpPost]
[Route("Login")]
[AllowAnonymous]
public async Task<IActionResult> Login([FromForm]LoginViewModel model)
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
if (model.Username == "test" && model.Password == "test")
{
var name = "Name";
var role = "Admin";
var email = "test123@gmail.com";
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Name, name),
new Claim(ClaimTypes.Email, email),
new Claim(ClaimTypes.Role, role)
};
var credientials = new SigningCredentials(
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_config["Jwt:JwtSecretKey"])),
SecurityAlgorithms.HmacSha256);
var securityToken = new JwtSecurityToken(
issuer: _config["Jwt:JwtIssuer"],
audience: _config["Jwt:JwtIssuer"],
claims: claims,
expires: DateTime.Now.AddMinutes(1),
signingCredentials: credientials
);
HttpContext.Response.Cookies.Append(
"JwtCookie",
"Bearer " + new JwtSecurityTokenHandler().WriteToken(securityToken),
new CookieOptions
{
Expires = DateTime.Now.AddMinutes(1),
HttpOnly = true,
Secure = true,
SameSite = SameSiteMode.Strict
});
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authenticationProperties = new AuthenticationProperties()
{
ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(1),
IsPersistent = true
};
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authenticationProperties);
#endregion
return Redirect($"{role}/Index");
Private.cshtml
@{
ViewData["Title"] = "Private";
}
<h2>Private Area</h2>
<input type="button" onclick="addUser()" value="Login" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
function addUser()
{
$.ajax
({
type: 'POST',
url: '/api/Test/AddUser'
}).done(function (data)
{
console.log("done");
}).fail(function (data, textStatus, xhr)
{
console.log("fail");
})
}
</script>
/ api / Test / AddUser方法
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HttpPost]
[Route("AddUser")]
public IActionResult AddUser()
{
var u = new User
{
SamAccountName = "Test",
Role = ""
};
_context.Add(u);
try
{
_context.SaveChanges();
}
catch (Exception e)
{
return BadRequest($"Cannot save: {e}");
}
return Ok();
}
我的问题是:
当我尝试调用api/Test/AddUser
方法时出现401错误。有没有一种方法可以自动通过授权标头发送包含JWT令牌的cookie,类似于CookieAuthentication
的方法吗?我知道这是因为我没有Authorization标头。但是,因为我将JWT令牌存储在HttpOnly cookie中,所以无法找到将令牌传递到授权标头中的方法。我可以添加授权{“ Bearer” +令牌}。我将不得不使用sessionStorage或使用普通的cookie,但这会弹出一些安全问题。我看过许多教程,但从未见过javascript如何传递其授权标头,大多数显示了通过Postman中的授权标头传递。
如果可以完成上述操作,是否可以将过期日期与CookieAuthentication
Cookie进行同步?由于无法像Cookie一样延长JWT令牌的到期日期,因此,如果它们使用两种不同类型的身份验证,该如何确保用户能够访问API和MVC?
该项目仅使用HTTPS,并且我在提交的表单中实现了防伪令牌。我应该防范任何攻击吗?
答案 0 :(得分:0)
有点晚了,但我认为您会通过这个答案找到问题的答案
How can I validate a JWT passed via cookies?
基本思路是创建一个中间件来拦截请求,检查cookie中是否包含token,提取token,配置请求的授权头。在此之后,您的请求应该具有带有令牌的授权标头,并且应该启动 Authorize 数据注释