gpt4 book ai didi

c# - ASP.Net OAuth 授权服务器 : Add an array as additional response parameter

转载 作者:行者123 更新时间:2023-11-30 17:35:34 36 4
gpt4 key购买 nike

我已经实现了自定义 OAuthAuthorizationServerProvider,并且我想在我的客户端请求访问 token 时在响应中添加一些额外的元素。

为此,我重写了 OAuthAuthorizationServerProvider.TokenEndpoint 方法,并成功地添加了一些单个元素(通过将它们添加到 context.AdditionalResponseParameters 字典中)。现在我有这样的回应:

{
"access_token": "wxoCtLSdPXNW9KK09PVhSqYho...",
"token_type": "bearer",
"expires_in": 1199,
"refresh_token": "uk0kFyj4Q2OufWKt4IzWQHlj...",
"toto": "bloblo",
"tata": "blabla"
}

这很好,但我的目标是添加一个数组以获得这种响应:

{
"access_token": "wxoCtLSdPXNW9KK09PVhSqYho...",
"token_type": "bearer",
"expires_in": 1199,
"refresh_token": "uk0kFyj4Q2OufWKt4IzWQHlj...",
"scopes": ["read", "write"]
}

我试图添加一个 json 解析的列表或数组而不是一个简单的字符串,但它给了我

"scopes": "[\"read\",\"write\"]"

那是解析成Json的字符串,不是Json数组:/

如何在 TokenEndpoint 响应中添加 Json 数组?

最佳答案

问题

当我们使用 app.OAuthBearerAuthenticationExtensions ,下一个链称为:

public static class OAuthBearerAuthenticationExtensions
{
public static IAppBuilder UseOAuthBearerAuthentication(this IAppBuilder app, OAuthBearerAuthenticationOptions options)
{
if (app == null)
throw new ArgumentNullException(nameof (app));
app.Use((object) typeof (OAuthBearerAuthenticationMiddleware), (object) app, (object) options);
app.UseStageMarker(PipelineStage.Authenticate);
return app;
}
}

然后是 OAuthAuthorizationServerMiddleware 类型的对象使用内部类 OAuthAuthorizationServerHandler其中 JsonTextWriter使用:

using (var jsonTextWriter = new JsonTextWriter((TextWriter) new StreamWriter((Stream) memory)))
{
jsonTextWriter.WriteStartObject();
jsonTextWriter.WritePropertyName("access_token");
jsonTextWriter.WriteValue(accessToken);
jsonTextWriter.WritePropertyName("token_type");
jsonTextWriter.WriteValue("bearer");
// and so on
this.Response.ContentLength = new long?((long) body.Length);
await this.Response.WriteAsync(body, this.Request.CallCancelled);
}

这里有两个限制:
*) JsonTextWriter是一个不能配置的纯类,它只是把string写成StringBuilder,所以Json.Settings = new MySettings()不能应用。还有 JsontTextWriter不支持复杂对象。数组只能写成 jsonTextWriter.WriteStartArray()jsonTextWriter.WriteEndArray() ,但这在 OAuthAuthorizationServerHandler 中被忽略了.
*) 有些类是内部的,不能被覆盖或继承。

微软开发人员似乎没有预见到这个问题,只是将自定义属性限制为IDictionary<string, string> .

解决方案1

而不是 app.UseOAuthBearerAuthentication(...)应用您自己的代码

app.Use<MyOAuthBearerAuthenticationMiddleware>(options);
app.UseStageMarker(PipelineStage.Authenticate);

您可以从 OAuthBearerAuthenticationMiddleware 派生一个类并用于您自己的目的。

解决方案2

覆盖 token 端点响应。这是一件棘手的事情。

1) 创建一个自定义中间件,它将包装其他调用并覆盖 Body 响应流。

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

public override async Task Invoke(IOwinContext context)
{
if (!context.Request.Path.Equals("/Token")
{
await Next.Invoke(context);
return;
}

using (var tokenBodyStream = new MemoryStream())
{
// save initial OWIN stream
var initialOwinBodyStream = context.Response.Body;

// create new memory stream
context.Response.Body = tokenBodyStream;

// other middlewares will will update our tokenBodyStream
await Next.Invoke(context);

var tokenResponseBody = GetBodyFromStream(context.Response);
var obj = JsonConvert.DeserializeObject(tokenResponseBody);
var jObject = JObject.FromObject(obj);

// add your custom array or any other object
var scopes = new Scope[];
jObject.Add("scopes", JToken.FromObject(scopes));
var bytes = Encoding.UTF8.GetBytes(jObject.ToString());
context.Response.Body.Seek(0, SeekOrigin.Begin);
await tokenBodyStream.WriteAsync(bytes, 0, bytes.Length);

context.Response.ContentLength = data.LongLength;
tokenBodyStream.Seek(0, SeekOrigin.Begin);

// get back result to the OWIN stream
await context.Response.Body.CopyToAsync(initialOwinBodyStream);
}
}
}

private string GetBodyFromStream(IOwinResponse response)
{
using (var memoryStream = new MemoryStream())
{
response.Body.Seek(0, SeekOrigin.Begin);
response.Body.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(memoryStream))
{
return reader.ReadToEnd();
}
}
}
}

2) 在UseOAuthBearerTokens之前使用新的中间件在认证启动方法中。

app.Use<AuthenticationPermissionsMiddleware>();
app.UseOAuthBearerTokens(options);

关于c# - ASP.Net OAuth 授权服务器 : Add an array as additional response parameter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40841971/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com