繁体   English   中英

如何使用Asp.Net Web API 2中的Owin OAuth2修改令牌端点响应主体

[英]How to modify token endpoint response body with Owin OAuth2 in Asp.Net Web API 2

我想从令牌端点响应修改响应主体。

我试图用MessageHandler拦截/ Token请求,但它不起作用。

我可以通过覆盖OAuthAuthorizationServerProvider.TokenEndpoint方法为响应添加一些额外的信息,但是我无法创建自己的响应主体。

有没有办法拦截/ Token请求?


编辑

我发现了如何从令牌端点响应中删除响应主体内容,如下所示: HttpContext.Current.Response.SuppressContent = true;

这似乎是实现我的目标的正确方法,但现在当我使用context.AdditionalResponseParameters.Add()方法添加我的自定义信息时, SuppressContent阻止任何改动。

现在我有这样的事情:

// Removing the body from the token endpoint response
HttpContext.Current.Response.SuppressContent = true;
// Add custom informations
context.AdditionalResponseParameters.Add("a", "test");

要简单地将新项添加到JSON令牌响应,您可以使用TokenEndpointResponse而不是TokenEndpoint通知。


如果您正在寻找一种方法来完全替换您自己的OAuth2授权服务器准备的令牌响应,那么很遗憾没有简单的方法可以做到这一点,因为OAuthAuthorizationServerHandler.InvokeTokenEndpointAsync在调用TokenEndpointResponse后不会检查OAuthTokenEndpointContext.IsRequestCompleted属性通知。

https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Security.OAuth/OAuthAuthorizationServerHandler.cs

这是一个已知的问题,但是当我建议解决它时,将它包含在Katana 3中为时已晚。

您应该尝试Owin.Security.OpenIdConnect.Server :它是为Katana 3.0和4.0设计的OAuthAuthorizationServerMiddleware的分支。

https://www.nuget.org/packages/Owin.Security.OpenIdConnect.Server/1.0.2

当然,它包括正确的检查以允许绕过默认令牌请求处理(这甚至是我在分叉时修复的第一件事)。

你几乎在那里+ Samoji @Samoji,真的帮助/启发我得到答案。

// Add custom informations
context.AdditionalResponseParameters.Add("a", "test");
// Overwrite the old content
var newToken = context.AccessToken;
context.AdditionalResponseParameters.Add("access_token", newToken);

我发现它只是用我的旧代替了我的旧代币。

此问题类似于如何扩展IdentityServer4工作流以运行自定义代码

因此,您可以在Startup中创建自定义中间件并在OAuth2服务之前注册它:

    public void Configuration(IAppBuilder app)
    {
        ....
        app.Use(ResponseBodyEditorMiddleware.EditResponse);

        app.UseOAuthAuthorizationServer(...);
        ...
    }

自定义中间件的位置是:

    public static async Task EditResponse(IOwinContext context, Func<Task> next)
    {
        // get the original body
        var body = context.Response.Body;

        // replace the original body with a memory stream
        var buffer = new MemoryStream();
        context.Response.Body = buffer;

        // invoke the next middleware from the pipeline
        await next.Invoke();

        // get a body as string
        var bodyString = Encoding.UTF8.GetString(buffer.GetBuffer());

        // make some changes to the body
        bodyString = $"The body has been replaced!{Environment.NewLine}Original body:{Environment.NewLine}{bodyString}";

        // update the memory stream
        var bytes = Encoding.UTF8.GetBytes(bodyString);
        buffer.SetLength(0);
        buffer.Write(bytes, 0, bytes.Length);

        // replace the memory stream with updated body
        buffer.Position = 0;
        await buffer.CopyToAsync(body);
        context.Response.Body = body;
    }

拦截请求和响应的最佳方法是通过MessageHandler,如果你想在请求到达管道中的IControllerFactory处理程序后避免这样做 - 显然在这种情况下使用自定义的'Attribute'

我过去曾使用MessageHandler拦截对api / token的请求,创建新请求并获取响应,创建新响应。

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        //create a new auth request
        var authrequest = new HttpRequestMessage();
        authrequest.RequestUri = new Uri(string.Format("{0}{1}", customBaseUriFromConfig, yourApiTokenPathFromConfig));

        //copy headers from the request into the new authrequest
        foreach(var header in request.Headers)
        {
            authrequest.Headers.Add(header.Key, header.Value);
        }

        //add authorization header for your SPA application's client and secret verification
        //this to avoid adding client id and secret in your SPA
        var authorizationHeader =
            Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", _clientIdFromConfig, _secretKeyFromConfig)));

        //copy content from original request
        authrequest.Content = request.Content;

        //add the authorization header to the client for api token
        var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(request.Headers.Authorization.Scheme, authorizationHeader);
        var response = await client.PostAsync(authrequest.RequestUri, authrequest.Content, cancellationToken);

        if(response.StatusCode == HttpStatusCode.OK)
        {
            response.Headers.Add("MyCustomHeader", "Value");
            //modify other attributes on the response
        }

        return response;
    }

这对我很有用。 但是,WebApiConfig.cs文件中需要此处理程序的配置(如果您使用的是ASP.NET MVC,则为RouteConfig.cs)。

你能详细说明在处理程序中对你不起作用的东西吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM