Я использую Identity Server 4 с .net Core 2.0.Когда я развернул веб-интерфейс API с помощью служб приложений Azure, он успешно развернулся, но при просмотре он показывает ошибку, как приложение перенаправляется слишком много раз.Это мой код Startup.cs
using System;
using System.Collections.Generic;
using Autofac;
using Dapper;
using FluentValidation.AspNetCore;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Mvms.Application.Abstract;
using Mvms.Application.Abstract.Services;
using Mvms.Data;
using Mvms.Data.IdentityClasses;
using Mvms.WebApi.Auth;
using Mvms.WebApi.Helpers;
using Mvms.WebApi.Resources;
using NetEscapades.AspNetCore.SecurityHeaders;
using NetEscapades.AspNetCore.SecurityHeaders.Infrastructure;
using Serilog;
using Swashbuckle.AspNetCore.Swagger;
namespace Mvms.WebApi
{
public class Startup
{
private readonly IServiceProvider _provider;
private readonly IConfiguration _configuration;
private readonly ILogger<DefaultCorsPolicyService> _logger;
private readonly IHostingEnvironment _environment;
public Startup(
IConfiguration configuration,
IServiceProvider provider,
ILogger<DefaultCorsPolicyService> logger,
IHostingEnvironment environment)
{
_provider = provider;
_logger = logger;
_environment = environment;
_configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
var conStr = _configuration.GetConnectionString("DefaultConnection");
var jwtAuthority = _configuration["JwtAuthority:WebSite"];
services.AddMultitenancy<TenantBasicInfo, CachingAppTenantResolver>();
services.AddDbContext<MvmsDataContext>(options => options.UseSqlServer(conStr), ServiceLifetime.Scoped);
services.AddScoped<ILanguageCache, LanguageCache>(); //one cache per http request
services.AddScoped<ILanguageIds, LanguageIds>(); //one cache per http request
SqlMapper.AddTypeHandler(new DateTimeHandler()); //UTC dates for Dapper
void IdentityOptions(IdentityOptions o)
{
//password options
o.Password.RequireDigit = true;
o.Password.RequireLowercase = true;
o.Password.RequireUppercase = true;
o.Password.RequireNonAlphanumeric = true;
o.Password.RequiredLength = 8;
o.Password.RequiredUniqueChars = 1;
}
services
.AddIdentity<ApplicationUser, ApplicationRole>(IdentityOptions)
.AddEntityFrameworkStores<MvmsDataContext>()
.AddDefaultTokenProviders();
services
.AddIdentityServer()
.AddSigningCertificate(_configuration, _environment)
.AddAspNetIdentity<ApplicationUser>()
.AddOperationalStore(x => x.ConfigureDbContext = db => db.UseSqlServer(conStr))
.AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources())
.AddInMemoryApiResources(IdentityServerConfig.GetApiResources())
.AddInMemoryClients(IdentityServerConfig.GetClients());
services.AddTransient<IResourceOwnerPasswordValidator, MultiTenantPasswordValidator>();
services
.AddAuthorization(x =>
{
x.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build();
})
.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwt =>
{
jwt.TokenValidationParameters = new TokenValidationParameters
{
IssuerValidator = (issuer, token, parameters) =>
{
var acc = _provider.GetService<IHttpContextAccessor>();
var apiTenant = acc.HttpContext.Request.Host.Value;
var authTenant = new Uri(issuer).Host;
//if (apiTenant == authTenant)
//{
// throw new SecurityTokenInvalidIssuerException();
//}
return issuer;
},
AudienceValidator = (audiences, token, parameters) => true
};
jwt.Audience = $"{jwtAuthority}/resources";
jwt.Authority = jwtAuthority;
jwt.RequireHttpsMetadata = false;
});
services.AddCors();
var validateAttribute = new ValidateModelAttribute(new LanguageDetector(), new MessageTranslator());
services
.AddMvcCore(x => x.Filters.Add(validateAttribute)) //validate models of all actions
.AddAuthorization()
.AddJsonFormatters(t => t.DateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fff'Z'")
.AddFluentValidation(x => x.RegisterValidatorsFromAssemblyContaining<Startup>())
.AddApiExplorer()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "Takamul MVMS", Version = "v1" });
c.DescribeAllEnumsAsStrings();
// Define the OAuth2.0 scheme that's in use (i.e. Implicit Flow)
c.AddSecurityDefinition("oauth2", new OAuth2Scheme
{
Type = "oauth2",
Flow = "password",
TokenUrl = "/connect/token",
Scopes = new Dictionary<string, string>
{
{ "api", "SPA and Mobile API" }
}
});
c.SchemaFilter<SwaggerFluentValidationProvider>();
c.SchemaFilter<SwaggerSampleModelProvider>();
c.OperationFilter<SwaggerAuthDefinitionProvider>();
c.OperationFilter<SwaggerLanguageHeaderProvider>();
});
var cors = new DefaultCorsPolicyService(_logger)
{
AllowedOrigins =
{
"http://localhost:4200", // for public portal local
"http://localhost:4201",//for admin portal local
"https://mvms-admin.azurewebsites.net", // for admin portal staging
"https://mvms-public.azurewebsites.net",//for public portal staging
"http://localhost:63342",
"https://letsadd.azureedge.net",
"https://mvms-release-cdn.azureedge.net",
"https://default.release.mvmsx.net/",
"https://citizenship.aramco.letsadd.org",
"https://ithra.aramco.letsadd.org"
} //ng serve + identity server
};
services.AddSingleton<ICorsPolicyService>(cors);
services.AddMemoryCache();
services.AddHttpClient();
}
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterAssemblyModules(Assemblies.Get());
}
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
ILanguageDetector detector,
IMessageTranslator translator,
IConfiguration config)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseStatusCodePages();
}
app.UseHsts();
if (env.IsDevelopment() || env.IsRelease())
{
app.UseSwagger();
}
else
{
//protect swagger
bool SwaggerIpFilter(HttpContext http)
{
return http.Request.Path.Equals("/swagger/v1/swagger.json")
&& http.Connection.RemoteIpAddress.ToString()
.Equals(_configuration["Swagger:Ip"], StringComparison.Ordinal);
}
app.MapWhen(SwaggerIpFilter, builder => builder.UseSwagger());
}
var policyCollection = new HeaderPolicyCollection()
.AddFrameOptionsDeny()
.AddXssProtectionBlock()
.AddContentTypeOptionsNoSniff()
.AddStrictTransportSecurityMaxAgeIncludeSubDomains(7776000) //minimum recommended value
.AddReferrerPolicyStrictOriginWhenCrossOrigin()
.RemoveServerHeader()
.RemoveCustomHeader("X-Powered-By")
.AddContentSecurityPolicy(builder =>
{
builder.AddObjectSrc().None();
builder.AddFormAction().Self();
builder.AddFrameAncestors().None();
});
app.UseSecurityHeaders(policyCollection);
app.UseCors(x =>
x.WithOrigins(
"http://localhost:4200", // for public portal local
"http://localhost:4201",//for admin portal local
"https://mvms-admin.azurewebsites.net", // for admin portal staging
"https://mvms-public.azurewebsites.net",//for public portal staging "http://localhost:63342",
"https://letsadd.azureedge.net",
"https://mvms-release-cdn.azureedge.net",
"https://default.release.mvmsx.net/",
"https://citizenship.aramco.letsadd.org",
"https://ithra.aramco.letsadd.org") // ng serve + web api
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowedToAllowWildcardSubdomains()); // tenant sub-domains
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Takamul MVMS V1");
c.OAuthClientId("client-spa");
c.OAuthClientSecret("secret");
c.OAuthScopeSeparator(" ");
c.OAuthUseBasicAuthenticationWithAccessCodeGrant();
c.DocExpansion(env.IsRelease() ? DocExpansion.List : DocExpansion.None);
});
app.AddAngularRoutes(env, config);
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
//do NOT cache the index because it contains names of the bundles
var cacheHeader = "public, max-age=31536000";
if (ctx.File.Name.EndsWith("index.html", StringComparison.OrdinalIgnoreCase) ||
ctx.File.Name.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
{
cacheHeader = "no-cache, no-store, must-revalidate";
}
ctx.Context.Response.Headers.Append("Cache-Control", cacheHeader);
}
});
app.CorrectStatusCode(loggerFactory, detector, translator); //set the http code 400 when it's needed
loggerFactory.AddSerilog();
app.UseMultitenancy<TenantBasicInfo>();
app.UseIdentityServer();
app.UseMvcWithDefaultRoute();
}
}
}
Он отлично работает в локальной среде.Как я думаю, проблема с конфигурацией https.