2017-09-26 68 views
0

我最近将项目从ASP.NET core更新为ASP.NET core 2.0 1.1。我使用openiddict进行验证。在将ASP.NET Core 1.1更新为ASP.NET Core 2.0之后,返回语句SignIn(ticket.Principal,ticket.AuthenticationScheme);给出了500错误

这是我的控制器,负责请求/响应。

[HttpPost("token")] 
public async Task<IActionResult> TokenAsync(OpenIdConnectRequest request) 
{ 
    try 
    { 
     var ticket = await _service.ExchangeTokenAsync(request); 

     return SignIn(ticket.Principal, ticket.Properties,ticket.AuthenticationScheme);; 

    } 
    catch (Exception ex) 
    { 
     return BadRequest(new OpenIdConnectResponse 
     { 
      Error = OpenIdConnectConstants.Errors.ServerError, 
      ErrorDescription = ex.Message 
     }); 
    } 
} 

这个return语句

return SignIn(ticket.Principal, ticket.Properties,ticket.AuthenticationScheme); 

抛出500内部服务器错误。这段代码完全适用于这个return语句,但是执行这个返回语句时会得到500个内部服务器错误。

这是我启动的文件方法。

public void ConfigureServices(IServiceCollection services) 
{ 
    var connectionString = Configuration["ConnectionStrings:ApplicationDbContext"]; 

    services.AddEntityFrameworkNpgsql(); 

    services.AddDbContext<ApplicationDbContext>(
     opts => 
     { 
      opts.UseNpgsql(connectionString, b => b.MigrationsAssembly("MenuSystem.Repository")); 
      opts.UseOpenIddict(); 
     } 
    ); 

    services.AddIdentity<ApplicationUser, IdentityRole>() 
     .AddEntityFrameworkStores<ApplicationDbContext>() 
     .AddDefaultTokenProviders(); 

    var validIssuer = Configuration["Token:Issuer"]; 
    services.AddAuthentication() 
     .AddJwtBearer(cfg => 
     { 
      cfg.TokenValidationParameters = new TokenValidationParameters 
      { 
       ValidIssuer = validIssuer, 
       IssuerSigningKey = securityKey, 

       ValidateIssuer = !String.IsNullOrEmpty(validIssuer), 
       ValidateAudience = false, 
       ValidateLifetime = true, 
       ValidateActor = false, 
       ValidateIssuerSigningKey = true 
      }; 
     }); 

    services.AddOpenIddict(options => 
    { 
     // Register the Entity Framework stores. 
     options.AddEntityFrameworkCoreStores<ApplicationDbContext>(); 
     options.AddMvcBinders(); 
     options.EnableTokenEndpoint("/api/account/token"); 
     options.UseJsonWebTokens(); 
     options.AllowPasswordFlow(); 
     options.AllowCustomFlow("urn:ietf:params:oauth:grant-type:facebook_access_token"); 
     options.AllowCustomFlow("urn:ietf:params:oauth:grant-type:google_access_token"); 
     options.AllowCustomFlow("urn:ietf:params:oauth:grant-type:microsoft_access_token"); 
     options.DisableHttpsRequirement(); 
     options.AddSigningKey(securityKey); 

    }); 


    services.Configure<IdentityOptions>(options => 
    { 
     // Password settings 
     options.Password.RequireDigit = true; 
     options.Password.RequiredLength = 8; 
     options.Password.RequireNonAlphanumeric = false; 
     options.Password.RequireUppercase = true; 
     options.Password.RequireLowercase = false; 

     // Lockout settings 
     options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30); 
     options.Lockout.MaxFailedAccessAttempts = 10; 

     // User settings 
     options.User.RequireUniqueEmail = true; 
    }); 


    services.AddCors(o => o.AddPolicy("CorsPolicy", builder => 
    { 
     builder.AllowAnyOrigin() 
       .AllowAnyMethod() 
       .AllowAnyHeader(); 
    })); 

    // Add framework services. 
    services.AddMvc(options => 
    { 
     options.Filters.Add(new GlobalExceptionFilter()); 
    }); 

    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
} 

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 
public virtual void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, RoleManager<IdentityRole> roleManager) 
{ 
    loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
    loggerFactory.AddDebug(); 

    app.UseAuthentication(); 
    app.UseCors("CorsPolicy"); 

    app.UseMvc(); 
} 

这里是调试日志

info: Microsoft.AspNetCore.Mvc.SignInResult[1] 
Project>  Executing SignInResult with authentication scheme (ASOS) and the following principal: System.Security.Claims.ClaimsPrincipal. 
Project> info: Microsoft.AspNetCore.Mvc.SignInResult[1] 
Project>  Executing SignInResult with authentication scheme (ASOS) and the following principal: System.Security.Claims.ClaimsPrincipal. 
Project> info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2] 
Project>  Executed action Project.Controllers.AccountController.TokenAsync (Project) in 15632.6224ms 
Project> info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2] 
Project>  Executed action Project.Controllers.AccountController.TokenAsync (Project) in 15632.6224ms 
Project> fail: Microsoft.AspNetCore.Server.Kestrel[13] 
Project>  Connection id "0HL852SU6TGOD", Request id "0HL852SU6TGOD:00000004": An unhandled exception was thrown by the application. 
Project> System.InvalidOperationException: The authentication ticket was rejected because the mandatory subject claim was missing. 
Project> at AspNet.Security.OpenIdConnect.Server.OpenIdConnectServerHandler.<SignInAsync>d__6.MoveNext() 
Project> --- End of stack trace from previous location where exception was thrown --- 
+0

什么是例外吗? – Tratcher

+0

它没有提供有关异常的任何信息,只是500内部服务器错误。 –

+1

检查您的应用程序日志。 – Tratcher

回答

0

这个答案是从原来的答案https://stackoverflow.com/a/44845552

你看到的是这样的事实造成的错误复制你的ClaimsPrincipal不具备强制sub索赔,如异常消息所示

为了解决这个问题,你有两个选择:手动添加sub索赔或要求身份使用sub作为名称标识要求

从属权利要求中加入由await _signInManager.CreateUserPrincipalAsync(user);...

// Note: while ASP.NET Core Identity uses the legacy WS-Federation claims (exposed by the ClaimTypes class), 
// OpenIddict uses the newer JWT claims defined by the OpenID Connect specification. To ensure the mandatory 
// subject claim is correctly populated (and avoid an InvalidOperationException), it's manually added here. 
if (string.IsNullOrEmpty(principal.FindFirstValue(OpenIdConnectConstants.Claims.Subject))) 
{ 
    identity.AddClaim(new Claim(OpenIdConnectConstants.Claims.Subject, await _userManager.GetUserIdAsync(user))); 
} 

返回本金......或者要求身份使用sub作为名称标识要求:

services.Configure<IdentityOptions>(options => 
{ 
    options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name; 
    options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject; 
    options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role; 
});