CORS-Problem in der .NET 4.5-Anwendung [geschlossen]C#

Ein Treffpunkt für C#-Programmierer
Anonymous
 CORS-Problem in der .NET 4.5-Anwendung [geschlossen]

Post by Anonymous »

Ich habe ein CORS-Problem in einer ASP.NET Web API 2-Anwendung mit OWIN-Authentifizierung (OAuth + JWT), die auf IIS gehostet wird.
Anfragen kommen von einem Angular-Frontend, aber CORS-Preflight-Anfragen (OPTIONS) schlagen fehl.
Was passiert
  • Browser sendet eine Preflight-OPTIONS-Anfrage
  • Der Server antwortet mit 405 / CORS-Fehler
  • Die tatsächliche API-Anfrage erreicht den Controller nie
  • Angular-Konsole zeigt CORS-Richtlinienblockierungsfehler an
Was ich bereits versucht habe
Ich habe bereits Änderungen in allen relevanten Ebenen vorgenommen, aber das Problem besteht weiterhin:
Startup.cs
  • Verwendet UseOAuthAuthorizationServer
  • UseJwtBearerAuthentication verwenden
  • Web-API über app.UseWebApi() hosten
WebApiConfig.cs
  • CORS mit EnableCorsAttribute aktiviert
  • Zulässige Ursprünge hinzugefügt über WhitelistUrls
  • Konfigurierte Routen und Filter />
  • Access-Control-Allow-*-Header hinzugefügt/entfernt
  • RequestFiltering-Einstellungen überprüft
  • Trotzdem schlägt CORS immer noch fehl, insbesondere während des Preflight.

Code: Select all

namespace Pheonix.Web
{
public partial class Startup
{
//
// The Client ID is used by the application to uniquely identify itself to Azure AD.
// The Metadata Address is used by the application to retrieve the signing keys used by Azure AD.
// The AAD Instance is the instance of Azure, for example public Azure or Azure China.
// The Authority is the sign-in URL of the tenant.
// The Post Logout Redirect Uri is the URL where the user will be redirected after they sign out.
//
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];

static string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
public void ConfigureAuth(IAppBuilder app)
{
ConfigureDbContext(app);
ConfigureCookieAuthentication(app);
//ConfigureGoogleAuth(app);
ConfigureOffice365Auth(app);
ConfigureJwtOAuth(app);
}

private static void ConfigureDbContext(IAppBuilder app)
{
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext(ApplicationUserManager.Create);
app.CreatePerOwinContext(ApplicationSignInManager.Create);
}

private static void ConfigureJwtOAuth(IAppBuilder app)
{
app.UseOAuthAuthorizationServer(new AppOAuthOptions());
app.UseJwtBearerAuthentication(new AppJwtOptions());

HttpConfiguration config = new HttpConfiguration();
app.UseWebApi(config);
}

private static void ConfigureCookieAuthentication(IAppBuilder app)
{
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
CookieSecure = CookieSecureOption.Always,
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(
validateInterval: TimeSpan.FromMinutes(500000),
regenerateIdentity: (manager, user) =>  user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ApplicationCookie))
}

});
}

private static void ConfigureGoogleAuth(IAppBuilder app)
{
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
{
ClientId = "200899829118-64tcj5ofov7iofnkbojs83tjb9bpnlr0.apps.googleusercontent.com",
ClientSecret = "IOMqL-RsFOGdYFniESnNgIdL"
});

// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
}

private static void ConfigureOffice365Auth(IAppBuilder app)
{
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
RedirectUri = postLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse();
context.Response.Redirect("/Error?message=" + context.Exception.Message);
return Task.FromResult(0);
}
}
});
}
}

public class AppOAuthOptions : OAuthAuthorizationServerOptions
{
public AppOAuthOptions()
{
TokenEndpointPath = new PathString("/token");
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(500000);
AccessTokenFormat = new AppJwtFormat(TimeSpan.FromMinutes(500000));
Provider = new AppOAuthProvider();
AllowInsecureHttp = true;
}
}

public class AppJwtFormat : ISecureDataFormat
{
private readonly TimeSpan _options;

public AppJwtFormat(TimeSpan options)
{
_options = options;
}

public string SignatureAlgorithm
{
get { return "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256"; }
}

public string DigestAlgorithm
{
get { return "http://www.w3.org/2001/04/xmlenc#sha256";  }
}

public string Protect(AuthenticationTicket data)
{
if (data == null) throw new ArgumentNullException("data");

var issuer = "localhost";
var audience = "all";
var key = Convert.FromBase64String("bXlzdXBlcnN0cm9uZ2tleWZvckFwcFByb3RlY3Rpb24=");
var now = DateTime.UtcNow;
var expires = now.AddMinutes(_options.TotalMinutes);
var signingCredentials = new SigningCredentials(
new InMemorySymmetricSecurityKey(key),
SignatureAlgorithm,
DigestAlgorithm);
var token = new JwtSecurityToken(issuer, audience, data.Identity.Claims,
now, expires, signingCredentials);

return new JwtSecurityTokenHandler().WriteToken(token);
}

public AuthenticationTicket Unprotect(string protectedText)
{
throw new NotImplementedException();
}
}

public class AppOAuthProvider : OAuthAuthorizationServerProvider
{
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity();
var username = context.OwinContext.Get("username");
var employee_id = context.OwinContext.Get("employee_id");
var role = context.OwinContext.Get("role");
var country = context.OwinContext.Get("country");
identity.AddClaim(new Claim(ClaimTypes.Email, username));
identity.AddClaim(new Claim(ClaimTypes.PrimarySid, employee_id));
identity.AddClaim(new Claim(ClaimTypes.Role, role));
identity.AddClaim(new Claim(ClaimTypes.Country, country));

context.Validated(identity);
return Task.FromResult(0);
}

public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
try
{
var username = context.Parameters["username"];
var employee_id = context.Parameters["employee_id"];

PhoenixEntities dbContext = new PhoenixEntities();
var user = dbContext.PersonEmployment.Where(x => x.OrganizationEmail == username.ToLower() && x.OrganizationEmail.Length > 0).First();// && x.IsEnabled == true);

if (user != null)
{
context.OwinContext.Set("username", username);
context.OwinContext.Set("employee_id", user.PersonID.ToString());
context.OwinContext.Set("role", user.Person.PersonInRole.Any() ? string.Join(",", user.Person.PersonInRole.Select(t => t.RoleID).ToList()) :  "20" );// RS: update  role by adding EDMS
context.OwinContext.Set("country", user.OfficeLocation.Value.ToString());

context.Validated();
}
else
{
context.SetError("Invalid credentials");
context.Rejected();
}
}
catch
{
context.SetError("Server error");
context.Rejected();
}
return Task.FromResult(0);
}
}

public class AppJwtOptions : JwtBearerAuthenticationOptions
{
public AppJwtOptions()
{
var issuer = "localhost";
var audience = "all";
var key = Convert.FromBase64String("bXlzdXBlcnN0cm9uZ2tleWZvckFwcFByb3RlY3Rpb24=");  ;

AllowedAudiences = new[] { audience };
IssuerSecurityTokenProviders = new[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, key)
};
}
}
}

Code: Select all

namespace Pheonix.Web
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services

//config.EnableCors();
ApiAccess.Initialize();

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
//json.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat;
json.SerializerSettings.DateFormatString = "MM/dd/yyyy";// "mmm-dd-yyyy";
json.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
json.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
//json.SerializerSettings.Converters.Add(new IsoDateTimeConverter());

GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));

config.MessageHandlers.Add(new BlockOptionsHandler());
var corsAttr = new EnableCorsAttribute(ConfigurationManager.AppSettings["WhitelistUrls"], "*", "*");
config.EnableCors(corsAttr);

// Configure Web API to use only bearer token authentication.
// Commented as it was not making the Controllers Authorize.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.Services.Add(typeof(IExceptionLogger), new PheonixExceptionLogger());
config.Services.Replace(typeof(IExceptionHandler), new PheonixExceptionHandler());

// Web API routes
config.MapHttpAttributeRoutes();

UnityConfig.RegisterComponents();
MappingDTOModelToModel.Configure();

// Or any other way to fetch your container.

//config.Routes.MapHttpRoute(
//    name: "DefaultApi",
//    routeTemplate: "api/{controller}/{id}",
//    defaults: new { id = RouteParameter.Optional }
//);
}
}
}

Code: Select all

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

namespace Pheonix.Web
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
HttpConfiguration config = GlobalConfiguration.Configuration;
MvcHandler.DisableMvcResponseHeader = true;

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
}

private readonly Stopwatch stopWatch = new Stopwatch();
private static readonly ILog Log4Net = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

protected void Application_BeginRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.StatusCode = 405;
HttpContext.Current.Response.End();
}

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
this.stopWatch.Start();
}

protected void Application_EndRequest(object sender, EventArgs e)
{
this.stopWatch.Stop();
Log4Net.ErrorFormat("Action : {0} : Time Utilized : {1} Seconds",
((System.Web.HttpApplication)(sender)).Context.Request.FilePath,
this.stopWatch.ElapsedMilliseconds / 1000);
this.stopWatch.Reset();
}
}
}

Code: Select all
























































































































































































































Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post