我正在尝试使用JWT承载令牌和google身份验证来实现对web API的身份验证。找到这个
answer
这很有帮助,但当它应该成功进行身份验证时,我得到了一个500,但有以下例外:
系统NullReferenceException:对象引用未设置为实例
指一个物体。在
微软AspNetCore。认证。JWTBearner。JwtBearerHandler。handleAuthenticationAsync()
微软AspNetCore。诊断学。developerCeptionPageMiddleware:
错误:执行时发生未处理的异常
要求
系统NullReferenceException:对象引用未设置为实例
指一个物体。在
微软AspNetCore。认证。JWTBearner。JwtBearerHandler。handleAuthenticationAsync()
在
微软AspNetCore。认证。JWTBearner。JwtBearerHandler。handleAuthenticationAsync()
在
微软AspNetCore。认证。AuthenticationHandler`1。验证teasync()
在
微软AspNetCore。认证。认证服务。AuthenticateTasync(HttpContext
上下文、字符串模式)位于
微软AspNetCore。认证。认证中间件。调用(HttpContext)
(上下文)在
微软AspNetCore。诊断学。developerCeptionPageMiddleware。调用(HttpContext)
(上下文)
当令牌无效时,我会得到401响应。
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
});
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o =>
{
o.SecurityTokenValidators.Clear();
o.SecurityTokenValidators.Add(
new GoogleTokenValidator(
client_id
));
});
services.AddScoped<PhotoService>();
services.AddScoped<TagService>();
services.AddScoped(_ => new BlobServiceClient(Configuration.GetConnectionString("AzureBlobStorage")));
services.AddDbContext<Data.DataContext>(x => x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "rvc", Version = "v1" }); });
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
// app.UseSwagger();
// app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "rvc v1"));
}
app.UseHttpsRedirection();
if (env.IsProduction())
{
app.UseSpa(spa => { });
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.ContentRootPath, "client")),
EnableDefaultFiles = true
});
}
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
这是我的Google TokenValidator:
public class GoogleTokenValidator : ISecurityTokenValidator
{
private readonly string _clientId;
private readonly JwtSecurityTokenHandler _tokenHandler;
public GoogleTokenValidator(string clientId)
{
_clientId = clientId;
_tokenHandler = new JwtSecurityTokenHandler();
}
public bool CanValidateToken => true;
public int MaximumTokenSizeInBytes { get; set; } = TokenValidationParameters.DefaultMaximumTokenSizeInBytes;
public bool CanReadToken(string securityToken)
{
return _tokenHandler.CanReadToken(securityToken);
}
public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
{
validatedToken = null;
try
{
validationParameters.ValidateIssuer = true;
var payload = GoogleJsonWebSignature.ValidateAsync(securityToken, new GoogleJsonWebSignature.ValidationSettings() { Audience = new[] { _clientId }}).Result; // here is where I delegate to Google to validate
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, payload.Name),
new Claim(ClaimTypes.Name, payload.Name),
new Claim(JwtRegisteredClaimNames.FamilyName, payload.FamilyName),
new Claim(JwtRegisteredClaimNames.GivenName, payload.GivenName),
new Claim(JwtRegisteredClaimNames.Email, payload.Email),
new Claim(JwtRegisteredClaimNames.Sub, payload.Subject),
new Claim(JwtRegisteredClaimNames.Iss, payload.Issuer),
};
var principle = new ClaimsPrincipal();
principle.AddIdentity(new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme));
return principle;
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}
}