Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/30.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# OWIN OAuth2中间件,重定向uri中有%23(#片段)_C#_Asp.net_Oauth_Owin_Owin Middleware - Fatal编程技术网

C# OWIN OAuth2中间件,重定向uri中有%23(#片段)

C# OWIN OAuth2中间件,重定向uri中有%23(#片段),c#,asp.net,oauth,owin,owin-middleware,C#,Asp.net,Oauth,Owin,Owin Middleware,我正在使用ASP.NET OWIN/Katana OAuthAuthorizationServer中间件,遇到了一个障碍 我有一些站点试图获取授权令牌,并创建了一个/oauth/authorize端点。但是,这些请求来自SPA(角度),在重定向URL中通常会有一个片段(#) 当发出请求时,它将重定向uri到该URL,但URL已编码(因此更改为%23)。然而,每当URL中出现%23时,状态总是设置为400,我似乎无法以任何方式阻止这一点。。。无法覆盖任何内容,并且没有Web.config保留的坏字

我正在使用ASP.NET OWIN/Katana OAuthAuthorizationServer中间件,遇到了一个障碍

我有一些站点试图获取授权令牌,并创建了一个
/oauth/authorize
端点。但是,这些请求来自SPA(角度),在重定向URL中通常会有一个片段(
#

当发出请求时,它将
重定向uri
到该URL,但URL已编码(因此
更改为
%23
)。然而,每当URL中出现
%23
时,状态总是设置为400,我似乎无法以任何方式阻止这一点。。。无法覆盖任何内容,并且没有Web.config保留的坏字符更改等

因此,我试图用一些占位符替换它,然后重定向回它自己。这很有效。然而,我似乎无法撤消我的URL更改。我需要将#放回URL并重定向到该URL,但OWIN中间件完全忽略任何将URL更改回的尝试。。。有人有什么想法吗?

哈希符号后的部分永远不会发送到服务器-例如,请参阅此处的许多类似问题


您可以通过Java脚本在客户端对placehodler进行后期处理,而不是尝试重定向到包含#的URL。

这是由以下因素造成的限制:

端点URI不得包含片段组件

构建在OAuth2规范基础上的OpenID Connect规范(以及流行的IdentityServer 3/4)似乎没有这个限制,因此您可以切换到OIDC或稍微弯曲OAuth2规范:)

在OWIN中间件中,将签入片段的存在

一种解决方法是通过将表示片段的
%23
替换为占位符来绕过此检查,并在位置重定向头发送到浏览器之前对其进行修补

要用占位符替换传入的
%23
,可以覆盖提供程序
MatchEndpoint
方法:

internal class OAuth2AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    public override Task MatchEndpoint(OAuthMatchEndpointContext context)
    {
        if (context.Request.Path.StartsWithSegments(context.Options.AuthorizeEndpointPath)
            && context.Request.QueryString.HasValue)
        {
            context.Request.QueryString = new QueryString(
                context.Request.QueryString.Value.Replace("%23", "__fragment__"));
        }

        return base.MatchEndpoint(context);
    }
}
public override async Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
    // Test if the redirect uri is allowed, if not call context.SetError("invalid_client");

    var redirectUri = context.RedirectUri.Replace("__fragment__", "#");
    var setter = context.GetType().GetProperty(nameof(context.RedirectUri))?.GetSetMethod(true);
    setter?.Invoke(context, new[] { redirectUri });
    context.Validated(redirectUri);
}
另一部分更为棘手,因为您似乎无法从provider类中默认执行此操作,因为
redirectUri
保存在provider类的内部

一种常见的方法是使用反射并在提供者
ValidateClientRedirectUri
方法中修改此
RedirectUri

internal class OAuth2AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    public override Task MatchEndpoint(OAuthMatchEndpointContext context)
    {
        if (context.Request.Path.StartsWithSegments(context.Options.AuthorizeEndpointPath)
            && context.Request.QueryString.HasValue)
        {
            context.Request.QueryString = new QueryString(
                context.Request.QueryString.Value.Replace("%23", "__fragment__"));
        }

        return base.MatchEndpoint(context);
    }
}
public override async Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
    // Test if the redirect uri is allowed, if not call context.SetError("invalid_client");

    var redirectUri = context.RedirectUri.Replace("__fragment__", "#");
    var setter = context.GetType().GetProperty(nameof(context.RedirectUri))?.GetSetMethod(true);
    setter?.Invoke(context, new[] { redirectUri });
    context.Validated(redirectUri);
}
另一种方法是向链中添加一个简单的中间件(在OAuth2中间件之前),该中间件监视响应(因此在等待下一个中间件之后),并在需要时修补位置头。这比设置私有属性要简单,但是现在补丁分布在两个不同的地方,不易维护

使用上面的方法,围绕重定向URI进行工作,如

https://server.com/#spa/path/123
请注意,您将向authorize endpoint redirect_uri参数传递URL编码的版本

将导致重定向到

https://server.com/#spa/path/123&access_token=<the_access_token>
https://server.com/#spa/path/123&access_token=

The#从未发送过,但这是一个经过编码的重定向url,因此它发送了%23,但遇到了。不过,这可能就是服务器拒绝它的原因,因为这样可能会发送不应该出现的私人信息?这不是正确的答案,因为所讨论的URL不包含
。在SPA+OAuth2/OIDC场景中使用哈希路由时,这是一个常见的用例。@WouterHuysentruit如果您仔细阅读,问题是“我需要将#放回URL并重定向到该URL”。服务器完全可以重定向到包含哈希片段的URL,这不是问题所在。问题是在
redirect\u uri
参数中获取URL编码的哈希片段,OWIN中间件似乎不支持该参数。但得到了f.e.的支持。同样,这个答案并没有回答这个问题。如何使%23与OWIN中间件一起工作的问题仍然没有答案。我认为我们最终被迫在客户端替换它。我把它改成了“....”或是一些通常不应该出现的东西。然后,angular应用程序截取并更改它,然后再允许路由前进。因此,这最终回答了我的问题