我在项目中使用具有OAuth授权的 ASP.NET Web API 。
我尝试使用最佳实践来解耦解决方案中的每个层。 我有一个Web项目,其中包含AngularJS文件和其他资源,这些项目已上传到www.example.com上,还有另一个项目是受保护的后端Web API控制器和服务器端内容,该项目已上传到api.example.com
在localhost上一切正常。当我将其发布到生产服务器时,对“ / token”的请求成功,但是在后端api中的任何控制器中请求任何操作均返回此错误: “从原点“ http://api.example.com/someRoute”对“ http://www.example.com”处XMLHttpRequest的访问已被CORS策略阻止:对预检请求的响应未通过访问控制检查:否“ Access-Control-Allow” -Origin'标头出现在所请求的资源上。”。
我在互联网上几乎所有有效链接中搜索了类似错误,但还没有答案!
我从后端API粘贴一些代码,以便您更好地理解我的方法。
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration httpConfig = new HttpConfiguration();
UnityConfig.Register(httpConfig);
ConfigureAuth(app);
WebApiConfig.Register(httpConfig);
app.UseWebApi(httpConfig);
#region AutoMapper Init
DtoMapping.Map();
#endregion
}
}
public void ConfigureAuth(IAppBuilder app)
{
// Configure the auth context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(AuthContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
//remove this line on production
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new SimpleAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthBearerTokens(OAuthServerOptions);
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
public class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
EnableCorsAttribute cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
config.MapHttpAttributeRoutes();
//...
}
}
[EnableCors("*", "*", "*")]
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return Task.FromResult<object>(null);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
IList<string> roleNames;
using (var _repo = new IdentityRepository())
{
var user = await _repo.FindUserAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "username or password is invalid.");
context.Rejected();
return;
}
roleNames = await _repo.GetRolesForUserAsync(user.Id);
}
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
foreach (var roleName in roleNames)
{
identity.AddClaim(new Claim(ClaimTypes.Role, roleName));
}
var props = new AuthenticationProperties(new Dictionary<string, string>
{
{
"userName", context.UserName
}
});
var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);
}
}
那么,有人可以帮我吗?
谢谢您的时间。
答案 0 :(得分:2)
万一有人想知道,这就是我解决此问题的方法:
这不是要在asp.net Web api中不设置cors策略(正如我已经提到的,我做了Microsoft docs website的建议。)
问题是 IIS未配置为处理OPTION动词方法! 并且由于飞行前请求使用的是OPTION方法,因此始终找不到404(来自网络服务器的拒绝),因此出现错误。
我应该提到的是,到目前为止,我仍然不知道为什么“ / token”在配置Web服务器之前起作用,以及为什么控制器没有相同的反应!
但是无论如何,问题就这样解决了。 希望有帮助!
答案 1 :(得分:0)
可能有点旧但值得一提的是,您需要在 global.asax 中添加 cors 标头
protected void Application_BeginRequest(object sender, EventArgs e)
{
var context = System.Web.HttpContext.Current;
var origins = System.Configuration.ConfigurationManager.AppSettings["AllowedCorsDomain"]?.TrimEnd('/');
context.Response.AddHeader("Access-Control-Allow-Origin", origins);
if (context.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
context.Response.AddHeader("Access-Control-Allow-credentials", "true");
context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, POST, DELETE, OPTIONS");
context.Response.AddHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type, origin, authorization, Accepts, accept, client-security-token, access-control-allow-headers");
context.Response.AddHeader("Access-Control-Max-Age", "86400");
context.Response.End();
}
}