我最近恢复了一个已经休眠了一年的项目的工作。它在AspNet Core 1.1上使用了Angular,并使用了OpenIddict 1.0的早期版本。它是使用VS2017开发的。
我将VS2017更新到最新版本(15.7.5),但是该项目无法编译,并且当我修复编译错误时,它将无法运行。因此,最终我忍受了决定,决定将项目更新为Asp Net Core 2.1,并使用最新版本的OpenIddict。我有项目,因此可以编译,但是在启动时会在标题中显示错误,即“ InvalidOperationException:方案已经存在:Bearer”
我看不出有什么问题。我知道在某个地方添加了另一个名为“ Bearer”的方案,但我不知道在哪里。我将其全部封闭在Startup.cs的下面。
using AspNet.Security.OpenIdConnect.Primitives;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SIAngular.DBContexts;
using SIAngular.Models;
using SIAngular.Services;
using OpenIddict.Abstractions;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authentication.JwtBearer;
namespace SIAngular
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddMvc();
services.AddDbContext<ApplicationDbContext>(options =>
{
// Configure the context to use Microsoft SQL Server.
options.UseSqlServer(Configuration.GetConnectionString("SqlConnection"));
// Register the entity sets needed by OpenIddict.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
options.UseOpenIddict();
});
// Register the Identity services.
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
//.AddDefaultTokenProviders();
// Configure Identity to use the same JWT claims as OpenIddict instead
// of the legacy WS-Federation claims it uses by default (ClaimTypes),
// which saves you from doing the mapping in your authorization controller.
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
});
services.AddOpenIddict()
// Register the OpenIddict core services.
.AddCore(options =>
{
// Configure OpenIddict to use the Entity Framework Core stores and models.
options.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>();
})
// Register the OpenIddict server services.
.AddServer(options =>
{
// Register the ASP.NET Core MVC services used by OpenIddict.
// Note: if you don't call this method, you won't be able to
// bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
options.UseMvc();
// Enable the token endpoint.
options .EnableTokenEndpoint("/connect/token");
options.AcceptAnonymousClients();
options.DisableScopeValidation();
// Note: the Mvc.Client sample only uses the code flow and the password flow, but you
// can enable the other flows if you need to support implicit or client credentials.
options.AllowPasswordFlow();
// Mark the "email", "profile" and "roles" scopes as supported scopes.
options.RegisterScopes(OpenIdConnectConstants.Scopes.Email,
OpenIdConnectConstants.Scopes.Profile,
OpenIddictConstants.Scopes.Roles);
// During development, you can disable the HTTPS requirement.
options.DisableHttpsRequirement();
// Note: to use JWT access tokens instead of the default
// encrypted format, the following lines are required:
//
options.UseJsonWebTokens();
options.AddEphemeralSigningKey();
})
// Register the OpenIddict validation services.
.AddValidation();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Authority = "http://localhost:53244/";
options.Audience = "resource_server";
options.RequireHttpsMetadata = false;
//options.IncludeErrorDetails = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = OpenIdConnectConstants.Claims.Subject,
RoleClaimType = OpenIdConnectConstants.Claims.Role
};
});
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}
public void Configure(IApplicationBuilder app)
{
app.UseDeveloperExceptionPage();
app.UseAuthentication();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
}
有人可以解释一下我在做什么错。我的意图是遵循OpenIddict示例,但显然我在某个地方出错了。
完整的堆栈跟踪如下:
System.InvalidOperationException: Scheme already exists: Bearer
at Microsoft.AspNetCore.Authentication.AuthenticationOptions.AddScheme(String name, Action`1 configureBuilder)
at Microsoft.AspNetCore.Authentication.AuthenticationBuilder.<>c__DisplayClass4_0`2.<AddSchemeHelper>b__0(AuthenticationOptions o)
at Microsoft.Extensions.Options.ConfigureNamedOptions`1.Configure(String name, TOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsManager`1.<>c__DisplayClass5_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsManager`1.Get(String name)
at Microsoft.Extensions.Options.OptionsManager`1.get_Value()
at Microsoft.AspNetCore.Authentication.AuthenticationSchemeProvider..ctor(IOptions`1 options, IDictionary`2 schemes)
at Microsoft.AspNetCore.Authentication.AuthenticationSchemeProvider..ctor(IOptions`1 options)
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitSingleton(SingletonCallSite singletonCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass4_0.<UseMiddleware>b__0(RequestDelegate next)
at Microsoft.AspNetCore.Builder.Internal.ApplicationBuilder.Build()
at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
at Microsoft.AspNetCore.Hosting.Internal.WebHost.StartAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String shutdownMessage)
at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token)
at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)
at SIAngular.Program.Main(String[] args) in C:\Users\username\Documents\Visual Studio 2017\Projects\SIAngular\Program.cs:line 20
答案 0 :(得分:4)
我终于找到了答案,这可能对OpenIddict专家是显而易见的,但对临时用户却不然。
由于我使用的是JWT,因此.AddValidation()
不需要注册OpenIddict服务器选项。事后看来,这是显而易见的,但我希望这对其他人有帮助。我确信我不是唯一一个愚蠢的人,因为被这个问题所吸引,当我现在查看OpenIddict示例时,我理解了,但是我认为注释“对于JWT令牌,请使用Microsoft JWT承载处理程序”。可以修改为“对于JWT令牌,请使用Microsoft JWT承载处理程序,并在下面删除对AddValidation的调用。