asp.net JWT和Google在Razor Page中的身份验证和授权

vqlkdk9b  于 2023-08-08  发布在  .NET
关注(0)|答案(1)|浏览(179)

我有一个使用谷歌auten的项目,我想使用JWT来授权,而不使用身份。它是不工作,虽然我看到了很多教程。这是我的代码,哪里错了?
这是程序中的配置(我写了应用程序。正确使用):

builder.Services
.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    //options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultSignInScheme = "Cookies";
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddCookie("Cookies")
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8
            .GetBytes(builder.Configuration.GetSection("AppSettings:Token").Value)),
        ValidateIssuer = false,
        ValidateAudience = false,
    };
})
.AddGoogle(
     options =>
    {
        IConfiguration googleAuthen = builder.Configuration.GetSection("Authentication:Google");
        options.SaveTokens = true;
        options.ClientId = googleAuthen["ClientId"];
        options.ClientSecret = googleAuthen["ClientSecret"];
        options.CorrelationCookie.SameSite = SameSiteMode.Lax;
    }
);

字符串
LoginModel中的代码:

public IActionResult OnPostLoginByGoogle()
    {
        string authenticationScheme = GoogleDefaults.AuthenticationScheme;

        var auth = new AuthenticationProperties
        {
            RedirectUri = Url.Page("/Login", pageHandler: "LoginGoogleCallback")
        };

        return new ChallengeResult(authenticationScheme, auth);
    }

    public async Task<IActionResult> OnGetLoginGoogleCallbackAsync()
    {
        var authenticateResult = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);

        if (!authenticateResult.Succeeded)
            return BadRequest(); // TODO: Handle this better.

        var userId = authenticateResult.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
        var userEmail = authenticateResult.Principal.FindFirstValue(ClaimTypes.Email);

        UserDTO loginedUser = _userRepository.GetUserByEmail((string)userEmail);
        
        string token = CreateToken(loginedUser);

        return RedirectToPage("/Students/TimeTable");

        //return LocalRedirect("/test");
    }

    public string CreateToken(UserDTO user)
    {
        List<Claim> claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, user.Email),
            new Claim(ClaimTypes.Role, "Student"),
        };
        var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(
            _configuration.GetSection("AppSettings:Token").Value));
        var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);
        
        var token = new JwtSecurityToken(
            claims: claims,
            expires: DateTime.Now.AddDays(1),
            signingCredentials: cred
            );
        var jwt = new JwtSecurityTokenHandler().WriteToken(token);
        
        return jwt;
    }


在另一个页面中,我写了[Authorize(Roles = "Student")],当指向该页面时,结果是HTTP 401 unAuthorized(我正在分配ClaimTypes.Role = Student以便于测试)

w46czmvw

w46czmvw1#

从你的代码中,你使用CreateToken方法生成token后,你直接重定向到目标页面而不携带那个token,所以即使你在token中配置了ClaimTypes.Role = Student,你也会得到401错误。您需要做的是确保请求携带生成的令牌。
方法之一是创建中间件。在这个中间件中,你可以从会话中获取令牌,然后将这个令牌添加到你的请求头中。

app.UseSession();

            //add token to request header.
            app.Use(async (context, next) =>
            {
                var token = context.Session.GetString("Token");
                if (!string.IsNullOrEmpty(token))
                {
                    context.Request.Headers.Add("Authorization", "Bearer " + token);
                }
                await next();
            });

            app.UseHttpsRedirection();

            app.UseAuthentication();
            
            app.UseAuthorization();

字符串
OnGetLoginGoogleCallbackAsync方法中,生成令牌后,将此令牌保存在会话中。

string token = CreateToken(loginedUser);
HttpContext.Session.SetString("Token",token);
return RedirectToPage("/Students/TimeTable");

相关问题