[英]ASP.NET Core Sign In with JWT
我使用 JWT 進行身份驗證,並將其存儲在 Cookies 中。我想使用HttpContext.SignInAsync登錄,我看到了很多使用基本 Cookie Auth 的示例,但沒有使用 JWT。
這是我的 Startup.cs
services.AddTransient<IUserRepository, UserRepository>();
services.AddTransient<ITokenService, TokenService>();
IdentityModelEventSource.ShowPII = true;
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
};
options.SaveToken = true;
options.Events = new JwtBearerEvents();
options.Events.OnMessageReceived = context =>
{
if (context.Request.Cookies.ContainsKey("X-Access-Token"))
{
context.Token = context.Request.Cookies["X-Access-Token"];
}
return Task.CompletedTask;
};
})
.AddCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.IsEssential = true;
});
這是我的登錄名(它目前正在工作,但使用 SignInAsync 會更好
public IActionResult Login(LoginModel loginModel, string returnUrl)
{
if (string.IsNullOrEmpty(loginModel.UserName) || string.IsNullOrEmpty(loginModel.Password))
{
ViewBag.Message = "Nem lehet üres";
return View("Index",loginModel);
}
IActionResult response = Unauthorized();
var validUser = GetUser(loginModel);
if (validUser != null)
{
generatedToken = _tokenService.BuildToken(_config["Jwt:Key"].ToString(), _config["Jwt:Issuer"].ToString(),
validUser);
if (generatedToken != null)
{
Response.Cookies.Append("X-Access-Token", generatedToken, new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.Strict, Secure=true });
Response.Cookies.Append("X-Username", loginModel.UserName, new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.Strict, Secure=true });
//Response.Cookies.Append("X-Refresh-Token", user.RefreshToken, new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.Strict });
// HttpContext.Session.SetString("Token", generatedToken);
if (returnUrl != null)
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("MainWindow");
}
}
else
{
ViewBag.Message = "Nem jo token";
return View("Index", loginModel);
}
}
else
{
ViewBag.Message = "Nem jó user";
return View("Index", loginModel);
}
}
這是我的令牌服務:
public class TokenService : ITokenService
{
private const double EXPIRY_DURATION_MINUTES = 30;
public string BuildToken(string key, string issuer, User user)
{
var claims = new[] {
new Claim(ClaimTypes.Name, user.Name),
new Claim(ClaimTypes.Role, user.Role),
new Claim(ClaimTypes.NameIdentifier,
Guid.NewGuid().ToString())
};
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new JwtSecurityToken(issuer, issuer, claims,
expires: DateTime.Now.AddMinutes(EXPIRY_DURATION_MINUTES), signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
}
public bool IsTokenValid(string key, string issuer, string token)
{
var mySecret = Encoding.UTF8.GetBytes(key);
var mySecurityKey = new SymmetricSecurityKey(mySecret);
var tokenHandler = new JwtSecurityTokenHandler();
try
{
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = issuer,
ValidAudience = issuer,
IssuerSigningKey = mySecurityKey,
}, out SecurityToken validatedToken);
}
catch
{
return false;
}
return true;
}
}
編輯 1 - 添加了問題
在這種情況下如何實現 HttpContext.SignInAsync?
我的啟動如下:
services.AddAuthentication(options =>
{
// custom scheme defined in .AddPolicyScheme() below
options.DefaultScheme = "JWT_OR_COOKIE";
options.DefaultChallengeScheme = "JWT_OR_COOKIE";
})
// Adding Jwt Bearer
.AddJwtBearer(options =>
{
....//do your staff
}).AddCookie("Cookies", options =>
{
options.LoginPath = "/account/login";
options.ExpireTimeSpan = TimeSpan.FromDays(1);
}).AddPolicyScheme("JWT_OR_COOKIE", "JWT_OR_COOKIE", options =>
{
// runs on each request
options.ForwardDefaultSelector = context =>
{
// filter by auth type
string authorization = context.Request.Headers[HeaderNames.Authorization];
if (!string.IsNullOrEmpty(authorization) && authorization.StartsWith("Bearer "))
return "Bearer";
// otherwise always check for cookie auth
return "Cookies";
};
});
添加更多代碼:
此答案中的一些代碼
在登錄發布方法中,我將以下內容添加到聲明中
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
我的令牌生成如下,當您登錄時,您將獲得令牌。
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: claims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
結果:
你的意思是你想從 jwt 讀取聲明並創建一個新的 cookie 身份驗證票,如下所示:
var jwtsecuritytoken = new JwtSecurityTokenHandler().ReadToken(token) as JwtSecurityToken;
var username = jwtsecuritytoken.Claims.FirstOrDefault(m => m.Type == ClaimTypes.Name).Value;
.......
//add other logic
.........
var claims = new Claim[]
{
new Claim(ClaimTypes.Name, username),
..........
};
var claimsIdentity = new ClaimsIdentity(claims);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
}
只需像下面這樣更改身份驗證
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "JwtBearerDefaults.AuthenticationScheme";
options.DefaultChallengeScheme = "JwtBearerDefaults.AuthenticationScheme";
options.DefaultSignInScheme = "JwtBearerDefaults.AuthenticationScheme";
})
身份驗證中間件自動執行登錄上下文
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.