首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为Web Api 2和OWIN令牌身份验证启用CORS

为Web Api 2和OWIN令牌身份验证启用CORS
EN

Stack Overflow用户
提问于 2016-03-29 21:09:22
回答 3查看 29.8K关注 0票数 32

我有一个ASP.NET MVC5Web项目(本地主机:81),它使用Knockoutjs从我的WebApi 2项目(本地主机:82)调用函数,以便在启用CORS的两个项目之间进行通信。到目前为止,一切都正常工作,直到我尝试实现对WebApi的OWIN令牌身份验证。

要在WebApi上使用/token端点,我还需要在端点上启用CORS,但经过几个小时的尝试和搜索解决方案后,它现在仍然有效,api/token仍然产生:

代码语言:js
复制
XMLHttpRequest cannot load http://localhost:82/token. No 'Access-Control-Allow-Origin' header is present on the requested resource.
代码语言:javascript
运行
复制
public void Configuration(IAppBuilder app)
{
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    TokenConfig.ConfigureOAuth(app);
    ...
}

TokenConfig

代码语言:javascript
运行
复制
public static void ConfigureOAuth(IAppBuilder app)
{
    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext(AppUserManager.Create);

    OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
    {
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
        Provider = new SimpleAuthorizationServerProvider()
    };

    app.UseOAuthAuthorizationServer(OAuthServerOptions);
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}

AuthorizationProvider

代码语言:javascript
运行
复制
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

    var appUserManager = context.OwinContext.GetUserManager();
    IdentityUser user = await appUserManager.FindAsync(context.UserName, context.Password);

    if (user == null)
    {
        context.SetError("invalid_grant", "The user name or password is incorrect.");
        return;
    }
    ... claims
}

IdentityConfig

代码语言:javascript
运行
复制
public static AppUserManager Create(IdentityFactoryOptions options, IOwinContext context)
{
    // Tried to enable it again without success. 
    //context.Response.Headers.Add("Access-Control-Allow-Origin", new[] {"*"});
    
    var manager = new AppUserManager(new UserStore(context.Get()));
        
    ...

    var dataProtectionProvider = options.DataProtectionProvider;
    if (dataProtectionProvider != null)
    {
        manager.UserTokenProvider =
                new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity"));
    }
    return manager;
}

编辑:

1.重要的是,直接打开端点(localhost:82/token)是可行的。

2.调用Api (localhost:82/api/..)webproject中的CORS也可以工作,因此为WebApi启用了CORS。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-05-02 00:15:19

我知道你的问题已经在评论中解决了,但我相信理解是什么导致了它以及如何解决这整个类问题是很重要的。

查看您的代码,我可以看到您正在设置Access-Control-Allow-Origin令牌终结点的标头超过一次:

代码语言:js
复制
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

在里面GrantResourceOwnerCredentials方法:

代码语言:js
复制
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

这个,看着CORS[CORS specifications](http://www.w3.org/TR/cors/) ]本身就是一个问题,因为:

如果响应包含零个或多个Access-Control-Allow-Origin头部值,则返回fail并终止此算法。

在您的场景中,框架将设置此标头两次,并了解CORS必须如何实现,这将导致在某些情况下(可能与客户端相关)删除标头。

以下问题的答案也证实了这一点:重复访问-控制-允许-回源:\*导致COR error?

因此,将调用移动到app.UseCors在调用ConfigureOAuth允许只设置一次CORS标头(因为owin管道在OAuth中间件处中断,并且永远不会到达Microsoft CORS中间件Token端点),并使Ajax调用正常工作。

为了获得更好的全局解决方案,您可以尝试再次app.UseCors在调用OAuth中间件之前,删除第二个Access-Control-Allow-Origin在内部插入GrantResourceOwnerCredentials..。

票数 49
EN

Stack Overflow用户

发布于 2018-05-27 21:59:59

按照以下步骤操作,您的API将正常工作:

删除任何代码,如

config.EnableCors(), [EnableCors(header:"*"....)]

从你的API。

转到startup.cs并添加下线app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

之前

代码语言:js
复制
ConfigureAuth(app);

Uou还需要安装Microsoft.owin.cors包才能使用此功能

票数 11
EN

Stack Overflow用户

发布于 2019-08-18 22:18:09

在不使用app.UseCors()的情况下解决问题

我也有同样的问题。我使用了一个Vue.Js客户端使用axois使用以下命令访问我的REST-API跨军团..。在我自己的Api服务器上无法添加Microsoft.Owin.Corsnuget由于版本冲突与其他第三方组件一起使用。所以我无法使用app.UseCors()方法,但我使用中间件管道解决了它。

代码语言:javascript
运行
复制
private IDisposable _webServer = null;

public void Start(ClientCredentials credentials)
{
    ...
    _webServer = WebApp.Start(BaseAddress, (x) => Configuration(x));
    ...
}

public void Configuration(IAppBuilder app)
{
    ...
    // added middleware insted of app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    app.Use();
    app.UseWebApi(config);
    ...
}

public class MyOwinMiddleware : OwinMiddleware
{
    public MyOwinMiddleware(OwinMiddleware next) :
        base(next)
    { }

    public override async Task Invoke(IOwinContext context)
    {
        var request = context.Request;
        var response = context.Response;

        response.OnSendingHeaders(state =>
        {
            var resp = (IOwinResponse)state;

            // without this headers -> client apps will be blocked to consume data from this api
            if (!resp.Headers.ContainsKey("Access-Control-Allow-Origin"))
                resp.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
            if (!resp.Headers.ContainsKey("Access-Control-Allow-Headers"))
                resp.Headers.Add("Access-Control-Allow-Headers", new[] { "*" });
            if (!resp.Headers.ContainsKey("Access-Control-Allow-Methods"))
                resp.Headers.Add("Access-Control-Allow-Methods", new[] { "*" });

            // by default owin is blocking options not from same origin with MethodNotAllowed
            if (resp.StatusCode == (int)HttpStatusCode.MethodNotAllowed &&
                HttpMethod.Options == new HttpMethod(request.Method))
            {
                resp.StatusCode = (int)HttpStatusCode.OK;
                resp.ReasonPhrase = HttpStatusCode.OK.ToString();
            }

        }, response);

        await Next.Invoke(context);
    }
}

因此,我创建了自己的中间件并操纵响应。GET调用只需要Access-Control-Allow头,而对于OPTIONS调用,我还需要操作StatusCode,因为axois.post()在发送POST之前首先使用OPTIONS-method进行调用。如果选项返回StatusCode 405,则永远不会发送帖子。

这解决了我的问题。也许这也能帮助到一些人。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36285253

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档