我是 ASP.NET Core 的新手。我尝试使用不和谐作为第 3 方登录服务登录(例如使用 facebook、google 登录)。
我可以成功登录并拥有我的用户对象、声明,并且我可以进入具有授权属性的类。下面你可以看到 UserIdentity 没问题。
但是假设用户想要返回登录页面。在这种情况下,我必须将他重定向到索引,但我想通过使用 Identity 检查用户是否经过身份验证,不幸的是,它是错误的并且没有声明等。据我了解,它可能与 cookie 或其他东西有关相似的。我还为类使用不同的属性(不是授权而是允许匿名)你可以在我的 Identity 对象下面看到
我正在分享我的验证码
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 对象的最佳方法是什么?
经过很长时间的分析,我发现了问题所在。
我刚刚将 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 对象。
您可以使用
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>();
}
您应该将 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();