使用具有单个用户帐户的默认Visual Stu@R_301_410@ 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
- }