可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am having trouble with securing my Web API using owin middle ware.
I have installed below package
Install-Package Microsoft.Owin.Cors -Version 2.1.0
And below is ConfigureAuth.cs code.
public void ConfigureAuth(IAppBuilder app)
{
//...
app.UseOAuthBearerTokens(OAuthOptions);
///Install-Package Microsoft.Owin.Cors -Version 2.1.0
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
}
I have hosted this WebApi project on a link , say ,http://webaip.azurewebsites.net
I am trying to access controller methods of above API from another site, say , http://mysite.azurewebsites.net
With above code in place I am able to invoke all the methods of API which are not secure. (Not decorated with Authorize attribute) Through javascript I am not able to invoke /Token for authentication. Below is my javascript code.
function LogIn() {
var loginData = {
grant_type: 'password',
username: 'username',
password: 'password',
};
$.ajax({
type: 'POST',
url: 'http://webaip.azurewebsites.net/Token/',
data: loginData
}).done(function (data) {
alert('logged in');
alert(data);
}).fail(function (data) {
alert('login problem')
}).error(function (data) {
alert('error invoking API');
});
return false;
}
I am getting below error
XMLHttpRequest cannot load http://webaip.azurewebsites.net/Token/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://mysite.azurewebsites.net' is therefore not allowed access. The response had HTTP status code 404.
Note: I have also tried to use below code with. It's not working for me either.
public static void Register(HttpConfiguration config)
{
var json = config.Formatters.JsonFormatter;
config.Formatters.Remove(config.Formatters.XmlFormatter);
//Need to have Microsoft.AspNet.WebApi.Cors package installed.
config.EnableCors(new EnableCorsAttribute("*","*","*"));
}
回答1:
After many hours of searching and looking at many many different solutions to this i have managed to get this working as per the below.
There are a number of reasons this is happening. Most likely you have CORS enabled in the wrong place or it is enabled twice or not at all.
If you are using Web API and Owin Token end point then you need to remove all the references to CORS in your Web API method and add the correct owin method because web api cors will not work with Token endpoint whilst Owin cors will work for both Web API and Token auth end points so lets begin:
- Make sure you have the Owin Cors package installed
- Remove any line that you have eg.config.EnableCors(); from your WebAPIconfig.cs
file
Go to your startup.cs file and make sure you execute Owin
Cors before any of the other configuration runs.
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
ConfigureAuth(app);
If your still having problems go to: Startup.Auth.cs and ensure you have the following in your ConfigureAuth method (you shouldnt need this if your startup.cs file is correct)
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
回答2:
the reason you are getting that error is because you have enabled CORS for the webapi but not for your /Token endpoint this gets initialised before the webapi pipeline gets its CORS settings.
So in addition to what you have already done in your WebApiConfig.cs
You should do the following: (assuming you have a standard WebAPI 2 project)
** Open File: App_Start/IdenityConfig.cs ** and add the line following // Allow cors for the ...
I have left the rest untouched as in the normal project template
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
// Allows cors for the /token endpoint this is different from webapi endpoints.
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); // <-- This is the line you need
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<IdentityDb>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = true,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// rest ommited ...
return manager;
}
回答3:
See my answer for this question
Also, if you use an angularJS as your client, you can have a look to my article that shows how to use Web API 2 (Individual User Account + CORS Enabled) from AngularJS Client.
Hope that helps.
回答4:
This solution can also be used:
open providers folder and then open ApplicationOAuthProvider.cs
inside GrantResourceOwnerCredentials() function paste this line:
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
回答5:
In case, anyone finds this useful
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "http://localhost:52436" });
await next();
});
回答6:
You should not have same header twice (I think it is a dictionary data structure)
In my case I had this line in a provider class which was not needed because I'm already enabling cores in startup.cs
//context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
in startup.cs I had and I kept:
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
回答7:
The first step is to install CORS nuget: Microsoft.AspNet.WebApi.Core
Enable it in Startup.cs
config.EnableCors();
then you can do anything you want:
to allow a controller to expose to external application, add this attribute:
[EnableCors([theHostYouWant], "*", "*")]
to allow external authentication, application need access to "/Token", to allow this, in
[YourApiFolder]/Providers/ApplicationoAuthProvider.cs
find
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
add
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "[YourDesiredHostAddress]" });
this covers both the controller and "/Token", the attribute can also added in the controller methods. So it can solve all the problem.