在asp.net core中成功登录后,User.Identity.IsAuthenticated在非auth方法中为false

问题描述 投票:0回答:4

我是 ASP.NET Core 的新手。我尝试使用不和谐作为第 3 方登录服务登录(例如使用 facebook、google 登录)。

我可以成功登录并拥有我的用户对象、声明,并且我可以进入具有授权属性的类。下面你可以看到 UserIdentity 没问题。

enter image description here

但是假设用户想要返回登录页面。在这种情况下,我必须将他重定向到索引,但我想通过使用 Identity 检查用户是否经过身份验证,不幸的是,它是错误的并且没有声明等。据我了解,它可能与 cookie 或其他东西有关相似的。我还为类使用不同的属性(不是授权而是允许匿名)你可以在我的 Identity 对象下面看到

enter image description here

我正在分享我的验证码

services.AddAuthentication(options =>
{
    options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
           
})
  .AddCookie(options =>
   {
      options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
      options.Cookie.MaxAge = options.ExpireTimeSpan;
      options.SlidingExpiration = true;
      options.EventsType = typeof(CustomCookieAuthenticationEvents);
      options.AccessDeniedPath = "/auth/DiscordAuthFailed";

    })
     .AddJwtBearer(options =>
      {
        options.SaveToken = true;
        options.TokenValidationParameters = new TokenValidationParameters()
        {
           ValidateIssuer = false,
           ValidateAudience = false,
           ValidateIssuerSigningKey = true,
           ValidIssuer = Configuration.GetValue<string>("Jwt:Issuer"),
           ValidAudience = Configuration.GetValue<string>("Jwt:Audience"),
           IssuerSigningKey = new SymmetricSecurityKey(
               Encoding.UTF8.GetBytes(Configuration.GetValue<string>("Jwt:EncryptionKey")))
        };
    })
     .AddOAuth("Discord",
         options =>
         {
           options.AuthorizationEndpoint = "https://discord.com/api/oauth2/authorize";
           options.TokenEndpoint = "https://discord.com/api/oauth2/token";
           options.Scope.Add("identify");
           options.Scope.Add("email");
           options.Scope.Add("guilds.join");
           options.Scope.Add("guilds.members.read");

          options.CallbackPath = "/auth/oauthCallback"; 
          options.ClientId = Configuration.GetValue<string>("Discord:ClientId");
          options.ClientSecret = Configuration.GetValue<string>("Discord:ClientSecret");
          options.UserInformationEndpoint = "https://discord.com/api/users/@me";
                                            
          options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
          options.ClaimActions.MapJsonKey(ClaimTypes.Name, "username");
          options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
          options.ClaimActions.MapJsonKey(ClaimTypes.IsPersistent, "verified"); 

          options.AccessDeniedPath = "/auth/DiscordAuthFailed";
          options.Events = new OAuthEvents()
           {                         
             OnCreatingTicket = async context =>
              {
               var request = new HttpRequestMessage(HttpMethod.Get,
               context.Options.UserInformationEndpoint);
               request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
               request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
                var response = await context.Backchannel.SendAsync(request,
                HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);

                response.EnsureSuccessStatusCode();

                var user=(await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync())).RootElement;

                context.RunClaimActions(user);

                }
          };
    });

services.AddTransient();

所以我的问题是,成功登录后在任何类/方法中访问 userIdentify 对象的最佳方法是什么?

c# asp.net-core oauth discord authorization
4个回答
5
投票

经过很长时间的分析,我发现了问题所在。

我刚刚将 DefaultAuthenticateScheme 更改为 CookieAuthenticationDefaults

services.AddAuthentication(options =>
{
    options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
           
})

并在我的登录方法中调用了sign方法。

var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
 
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, result.Principal);

成功登录后,我可以在任何操作中获取 HttpContext.User 对象。


2
投票

如果您有多个身份验证方案(例如 JWT 身份验证、Cookie 身份验证)一起运行,则 User.Identity.IsAuthenticate 返回 false。

为了克服这个问题,您可以添加身份验证策略方案,该方案根据传入请求选择/过滤要使用的身份验证方法。

您可以参考 Microsoft 的这篇博客文档,它为我完成了这项工作。


1
投票

您可以使用

GetUserAsync
方法来检查用户是否已登录。您需要使用
UserManager
下的
AspNetCore.Identity
类来使用上述方法。在你的情况下,它看起来像这样:

您首先需要在

UserManager
中配置您的
Startup.cs
类,只需向
Configure
方法添加一个参数即可:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager)
{
 // your code
}

然后你可以在你的

Controller
方法中使用它:

[Route("Account")]
public class AccountController: Controller
{

   private UserManager<ApplicationUser> _userManager;

   public AccountController(UserManager<ApplicationUser> userManager)
   {
     _userManager = userManager;
   }

   [Route("Login")]
   [AllowAnonymous]
   public IActionResult Login()
   {
      ClaimsPrincipal currentUser = User;
      var user =_userManager.GetUserAsync(User).Result; 
      if(user.Identity.IsAuthenticated)
      {
        //redirect here
      }  

      return View();
   }
}

您需要更新您的

ConfigureServices
以包含默认身份:

public void ConfigureServices(IServiceCollection services)  
{  
    services.AddDbContext<ApplicationDbContext>(options =>  
        options.UseMySql(  
            Configuration.GetConnectionString("DefaultConnection")));  
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)  
        .AddEntityFrameworkStores<ApplicationDbContext>();  
} 

0
投票

您应该将 DefaultAuthenticationTypes 更改为

DefaultAuthenticationTypes.ApplicationCookie

例如在配置服务中

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = DefaultAuthenticationTypes.ApplicationCookie;
})
    .AddCookie(DefaultAuthenticationTypes.ApplicationCookie, options =>
    {
        // true by default   
        options.SlidingExpiration = true;
        // 14 days by default
        options.ExpireTimeSpan = TimeSpan.FromMinutes(120);
        options.Cookie.IsEssential = true;
        options.Cookie.HttpOnly = true;
        options.Cookie.SameSite = SameSiteMode.None;

        options.LoginPath = "/Account/Login";
        options.LogoutPath = "/Account/SignedOut";
    });

builder.Services.AddSession(options =>
{
    options.Cookie.SameSite = SameSiteMode.None;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.Cookie.IsEssential = true;
});

在控制器中登录:

        var verificationResult = await AuthenticateUser(Input.Email, Input.Password);

        if (verificationResult)
        {

            var claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.Name, Input.Email));
            ClaimsIdentity userIdentity =
                new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
            ClaimsPrincipal principal =
                new ClaimsPrincipal(userIdentity);
            await HttpContext.SignInAsync(DefaultAuthenticationTypes.ApplicationCookie, principal,
                new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc = DateTime.UtcNow.AddDays(7)
                });
            AuthenticateResult authenticateResult =
                await HttpContext.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie);

            var res=User.Identity.IsAuthenticated;
            return Redirect(returnUrl);
        }

退出:

        if (User.Identity.IsAuthenticated)
        {
            HttpContext.SignOutAsync(DefaultAuthenticationTypes.ApplicationCookie);
        }

        return Page();
© www.soinside.com 2019 - 2024. All rights reserved.