我正在尝试允许用户使用他们的Google帐户登录我的ASP.NET Core Blazor应用程序。每当我进入我的应用程序/登录/谷歌登录时,一切都如预期一样。我被重定向到谷歌的登录页面,然后我可以选择一个登录帐户。选择我的帐户后,需要几秒钟才能加载,然后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格式为JSON的API中得到的响应。基本上,它告诉我本金是空的,我本可以猜到,但其余的也是空的。这是怎么回事?这可能只是我在谷歌端的范围问题吗?我有理由相信这不是问题所在,因为我的应用程序应该能够在不崩溃的情况下使用任何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");
});
}
}
如果你需要任何额外的信息或代码,我很乐意尽快提供。
这句话可以说是我项目中相当重要的一部分,因为谁知道是什么原因阻止了与谷歌的通信。
services.AddIdentity<User, Role>().AddEntityFrameworkStores<Context>();
我现在基本上没有UserManager和RoleManager,只写了访问AspNetUsers等的手动方法。
可能不是一个真正的解决方案,但它就是这样。