我试图允许用户在我的 ASP.NET Core Blazor 应用程序上使用其 Google 帐户登录。每当我进入我的 app/login/google-login 时,一切都会按预期进行。我被重定向到谷歌的登录页面,我可以选择一个帐户来登录。选择我的帐户后,加载需要几秒钟,然后 Visual Studio 2019 告诉我:
System.NullReferenceException: 'Object reference not set to an instance of an object.' Microsoft.AspNetCore.Authentication.AuthenticateResult.Principal.get returned null.
在这段代码中:
var claims = response.Principal.Identities.FirstOrDefault().Claims.Select(claim => new
{
claim.Issuer,
claim.OriginalIssuer,
claim.Type,
claim.Value
});
一些调试揭示了以下内容:
{"succeeded":false,"ticket":null,"principal":null,"properties":null,"failure":null,"none":true}
这是我从 Google API 得到的响应,格式为 JSON。基本上它告诉我主体为空,我可以猜到,但其余部分也为空。这里发生了什么?这是否只是我在 Google 端的范围的问题?我有理由相信这不是问题,因为我的应用程序应该能够处理任何 API 响应而不会崩溃,对吗?
这是我的 LoginController.cs 类:
[AllowAnonymous, Route("login")]
public class LoginController : Controller
{
[Route("google-login")]
public IActionResult GoogleLogin()
{
var properties = new AuthenticationProperties { RedirectUri = Url.Action("GoogleResponse") };
return Challenge(properties, GoogleDefaults.AuthenticationScheme);
}
[Route("google-response")]
public async Task<IActionResult> GoogleResponse()
{
var response = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
var claims = response.Principal.Identities.FirstOrDefault().Claims.Select(claim => new
{
claim.Issuer,
claim.OriginalIssuer,
claim.Type,
claim.Value
});
return Json(claims);
}
}
这是我的 Startup.cs:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
//services.AddSingleton<WeatherForecastService>();
services.AddDbContext<Context>(options => options.UseSqlServer(Configuration.GetConnectionString("Context")));
services.AddIdentity<User, Role>().AddEntityFrameworkStores<Context>();
services.AddHttpContextAccessor();
services.AddScoped<IReservationService, ReservationService>();
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/login/google-login";
})
.AddGoogle(options =>
{
options.ClientId = Configuration["Google:ClientID"];
options.ClientSecret = Configuration["Google:ClientSecret"];
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
如果您需要任何其他信息或代码,我很乐意尽快提供。
这条线可以说是我项目中相当大的一部分,它阻止了与 Google 的通信,谁知道什么原因。
services.AddIdentity<User, Role>().AddEntityFrameworkStores<Context>();
我现在基本上只是继续没有 UserManager 和 RoleManager,只是编写手动方法来访问 AspNetUsers 等。
可能不是真正的解决方案,但它就是这样。
来晚了,但最近遇到了同样的错误。我有这个日志:
The cookie 'idsrv.external' has set 'SameSite=None' and must also set 'Secure'.
我发现如果cookie设置了SameSite=None,回调Url必须是https才能接收来自Google的Cookie。因为您的应用程序没有 Cookie,所以无法通过以下行进行授权:
var properties = new AuthenticationProperties { RedirectUri = Url.Action("GoogleResponse") };
将开发者 URL 更改为 https 将解决此问题。 示例:https://localhost:5000