使用具有单个用户帐户的默认Visual Studio 2013 Web API项目模板,并使用application / xml的Accept标头发布到/ token端点,服务器仍然以
JSON方式返回响应:
{"access_token":"...","token_type":"bearer","expires_in":1209599}
有没有办法将令牌恢复为XML?
解决方法
根据
RFC6749,响应格式应该是JSON,Microsoft会相应地实现它.我发现JSON格式是在Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerHandler内部类中实现的,没有任何扩展方式.
我还遇到了在XML中进行令牌响应的需要.
我提出的最佳解决方案是在Accept头中声明时实现将JSON转换为XML的HttpModule.
public class OAuthTokenXmlResponseHttpModule : IHttpModule { private static readonly string FilterKey = typeof(OAuthTokenXmlResponseHttpModule).Name + typeof(MemoryStreamFilter).Name; public void Init(HttpApplication application) { application.BeginRequest += ApplicationOnBeginRequest; application.EndRequest += ApplicationOnEndRequest; } private static void ApplicationOnBeginRequest(object sender,EventArgs eventArgs) { var application = (HttpApplication)sender; if (ShouldConvertToXml(application.Context.Request) == false) return; var filter = new MemoryStreamFilter(application.Response.Filter); application.Response.Filter = filter; application.Context.Items[FilterKey] = filter; } private static bool ShouldConvertToXml(HttpRequest request) { var isTokenPath = string.Equals("/token",request.Path,StringComparison.InvariantCultureIgnoreCase); var header = request.Headers["Accept"]; return isTokenPath && (header == "text/xml" || header == "application/xml"); } private static void ApplicationOnEndRequest(object sender,EventArgs eventArgs) { var context = ((HttpApplication) sender).Context; var filter = context.Items[FilterKey] as MemoryStreamFilter; if (filter == null) return; var jsonResponse = filter.ToString(); var xDocument = JsonConvert.DeserializeXNode(jsonResponse,"oauth"); var xmlResponse = xDocument.ToString(SaveOptions.DisableFormatting); WriteResponse(context.Response,xmlResponse); } private static void WriteResponse(HttpResponse response,string xmlResponse) { response.Clear(); response.ContentType = "application/xml;charset=UTF-8"; response.Write(xmlResponse); } public void Dispose() { } } public class MemoryStreamFilter : Stream { private readonly Stream _stream; private readonly MemoryStream _memoryStream = new MemoryStream(); public MemoryStreamFilter(Stream stream) { _stream = stream; } public override void Flush() { _stream.Flush(); } public override int Read(byte[] buffer,int offset,int count) { return _stream.Read(buffer,offset,count); } public override void Write(byte[] buffer,int count) { _memoryStream.Write(buffer,count); _stream.Write(buffer,count); } public override string ToString() { return Encoding.UTF8.GetString(_memoryStream.ToArray()); } #region Rest of the overrides public override bool CanRead { get { throw new NotImplementedException(); } } public override bool CanSeek { get { throw new NotImplementedException(); } } public override bool CanWrite { get { throw new NotImplementedException(); } } public override long Seek(long offset,SeekOrigin origin) { throw new NotImplementedException(); } public override void SetLength(long value) { throw new NotImplementedException(); } public override long Length { get { throw new NotImplementedException(); } } public override long Position { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } #endregion }