簡體   English   中英

ASP.NET 核心登錄JWT

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM