Mor*_*ael 14 forms json asp.net-web-api owin asp.net-web-api2
我在visual studio中创建了一个新的WebAPI解决方案,并且正在使用代码来尝试了解最新情况.
我有一个测试API,它全部启动并运行授权控制器和另一个实现所有实际功能的控制器.
控制器(API)都通过接收JSON并使用JSON进行回复来工作,但/ Token请求除外.这必须是:
Content-Type: application/x-www-form-urlencoded
Run Code Online (Sandbox Code Playgroud)
否则我只是得到一个错误.
创建此端点的代码部分似乎是这样的:
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = false
};
Run Code Online (Sandbox Code Playgroud)
像这样调用它会导致200 Success响应,带有Bearer令牌:
$("#token_button").click(function ()
{
var username = $("#token_email").val();
var password = $("#token_password").val();
postData("Token", "grant_type=password&username=" + username + "&password=" + password, "application/x-www-form-urlencoded", function (data)
{
user = data;
$("#feedback_display").html(user.access_token);
}, function ()
{
user = null;
});
});
Run Code Online (Sandbox Code Playgroud)
像这样调用它会导致400响应:
$("#token_button").click(function ()
{
var username = $("#token_email").val();
var password = $("#token_password").val();
var data = {
"grant_type": "password",
"username": username,
"password": password
}
postData("Token", JSON.stringify(data), "application/json", function (data)
{
user = data;
$("#feedback_display").html(user.access_token);
}, function ()
{
user = null;
});
});
Run Code Online (Sandbox Code Playgroud)
回应机构是:
{"error":"unsupported_grant_type"}
Run Code Online (Sandbox Code Playgroud)
这里唯一的区别是用于传输请求的编码.我看的所有示例都使用表单编码来请求此令牌.
在/ api/Account/ExternalLogin下的代码上放置一个断点,永远不会被击中.
这是否只有接受表单编码的原因?如果不是,我怎么能改变控制器接受JSON?
或者我刚做了一些蠢事?
Fed*_*uma 14
使用application/x-www-form-urlencoded
as 的原因Content-Type
很简单:OAuth2规范(RFC 6749)要求令牌请求使用此内容类型.
任何其他内容类型都将破坏与OAuth2兼容的客户端兼容性.我建议你不要改变这个标准行为.
注意
请注意:
postData("Token", data, "application/json", function (data)
{
//...
}
Run Code Online (Sandbox Code Playgroud)
只是因为你根本没有发送JSON!即使您添加application/json
了Content-Type
标头,您的请求主体也会被序列化为表单键值对(AJAX调用中的jQuery默认对象序列化).
默认的实现OAuthAuthorizationServerMiddleware
(更确切地说是内部使用的OAuthAuthorizationServerHandler
)Microsoft.Owin.Security.OAuth
只是忽略Content-Type
标题并尝试将请求主体作为一个表单来读取.
客户的技术专家要求我们的 /token 端点可以在正文中使用“application/x-www-form-urlencoded”和“application/json”格式。所以我必须实现它,尽管它违反了规范。
创建一个 Owin 中间件,如果路径为“/api/token”且内容类型为“application/json”,则将 JSON 正文转换为 Url 编码的正文。不要忘记在 Startup.cs 中注册它。
public sealed class JsonBodyToUrlEncodedBodyMiddleware : OwinMiddleware
{
public JsonBodyToUrlEncodedBodyMiddleware(OwinMiddleware next)
: base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
if (string.Equals(context.Request.ContentType, "application/json")
&& string.Equals(context.Request.Method, "POST", StringComparison.InvariantCultureIgnoreCase)
&& context.Request.Path == new PathString("/avi/token/"))
{
try
{
await ReplaceJsonBodyWithUrlEncodedBody(context);
await Next.Invoke(context);
}
catch (Exception)
{
context.Response.StatusCode = (int) HttpStatusCode.BadRequest;
context.Response.Write("Invalid JSON format.");
}
}
else
{
await Next.Invoke(context);
}
}
private async Task ReplaceJsonBodyWithUrlEncodedBody(IOwinContext context)
{
var requestParams = await GetFormCollectionFromJsonBody(context);
var urlEncodedParams = string.Join("&", requestParams.Select(kvp => $"{kvp.Key}={kvp.Value}"));
var decryptedContent = new StringContent(urlEncodedParams, Encoding.UTF8, "application/x-www-form-urlencoded");
var requestStream = await decryptedContent.ReadAsStreamAsync();
context.Request.Body = requestStream;
}
private static async Task<Dictionary<string, string>> GetFormCollectionFromJsonBody(IOwinContext context)
{
context.Request.Body.Position = 0;
var jsonString = await new StreamReader(context.Request.Body).ReadToEndAsync();
var requestParams = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString);
return requestParams;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6044 次 |
最近记录: |