DotNetOpenAuth不适用于MVC 5 RC

我一直在DotNetOpenAuth工作很多。 首先我们使用了5.0.0-alpha1,但是我们切换到了v4.0.30319,因为我们无法find导致我们问题的原因。

我们正在Visual Studio 2013中使用MVC 5 RC在.NET 4.5.1 RC上构build一个C#Web API项目。我们实现了IAuthorizationServerHostINonceStoreICryptoKeyStore

我们遇到的问题是围绕以下情况:

 public class TokensController : Controller { private readonly AuthorizationServer authorizationServer = new AuthorizationServer(new MyAuthorizationServer()); /// <summary> /// This action will handle all token requests. /// </summary> /// <returns>The action result that will output the token response.</returns> [HttpPost] public ActionResult Index() { var outgoingWebResponse = this.authorizationServer.HandleTokenRequest(this.Request); return outgoingWebResponse.AsActionResult(); } } 

return outgoingWebResponse.AsActionResult(); 一个源于DotNetOpenAuth.MessagingMessagingUtilities静态类的方法。 DotNetOpenAuth.Core (包含此代码)引用MVC 4.0,并且HttpResponseMessageActionResult类从ActionResultinheritance。

这意味着与MVC 5不兼容的DotNetOpenAuth的当前版本。编译并试图运行这将只是500错误。

有没有人有任何想法如何可以很容易地修复(或者不)?

我没有注意到DotNetOpenAuth Nuget包在我的包上写了5.0。 所以在重新安装软件包并再次添加assemblyBinding之后:

 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="5.0.0.0" /> </dependentAssembly> </assemblyBinding> 

这让我们更进一步。 现在错误归结为:

试图通过安全透明方法'DotNetOpenAuth.Messaging.MessagingUtilities.AsActionResult(DotNetOpenAuth.Messaging.OutgoingWebResponse)'访问安全关键types'System.Web.Mvc.ActionResult'失败。

修复可用。

安装NuGet包DotNetOpenAuth.Mvc5并将AsActionResult()所有用法改为AsActionResultMvc5()

在GitHub https://github.com/DotNetOpenAuth/DotNetOpenAuth/issues/307进一步debugging并与DotNetOpenAuth的人交谈之后,得出的结论是MVC 5有一个新的安全模型。

绑定redirect因此是不够的。 直到进一步有两个select:

1)抓住DotNetOpenAuth源代码,并从所有项目中删除[assembly:AllowPartiallyTrustedCallers]。 重新编译和成员禁用强名称validationsn -Vr *。 此代码无法在中等信任环境中运行。

2)抓住DotNetOpenAuth源代码,并针对MVC 5进行重新编译。

根据关于GitHub的讨论,最好的解决scheme是将所有相关的MVC内容转移到单独的程序集中。

解决scheme(可以使用当前的beta nuget包):

  • 创build一个ActionResult类包装HttpResponseMessage

     public class WrapperHttpResponseMessageResult : ActionResult { private readonly HttpResponseMessage _response; public WrapperHttpResponseMessageResult(HttpResponseMessage response) { _response = response; } public override void ExecuteResult(ControllerContext context) { HttpResponseBase responseContext = context.RequestContext.HttpContext.Response; responseContext.StatusCode = (int)_response.StatusCode; responseContext.StatusDescription = _response.ReasonPhrase; foreach (KeyValuePair<string, IEnumerable<string>> keyValuePair in (HttpHeaders)_response.Headers) { foreach (string str in keyValuePair.Value) responseContext.AddHeader(keyValuePair.Key, str); } if (_response.Content != null) { _response.Content.CopyToAsync(responseContext.OutputStream).Wait(); } } } 
  • 更改return outgoingWebResponse.AsActionResult();new WrapperHttpResponseMessageResult(outgoingWebResponse);

WrapperHttpResponseMessageResult代码是从WrapperHttpResponseMessageResult中复制的,所以它们执行相同的function。

使用这个来确保授权者得到正确的传递。

  public class MvcAuthorizer : WebAuthorizer { public ActionResult BeginAuthorization() { return new MvcOAuthActionResult(this); } public new ActionResult BeginAuthorization(Uri callback) { this.Callback = callback; return new MvcOAuthActionResult(this); } } 

'然后正确地检索它

 public class MvcOAuthActionResult : ActionResult { private readonly WebAuthorizer webAuth; public MvcOAuthActionResult(WebAuthorizer webAuth) { this.webAuth = webAuth; } public override void ExecuteResult(ControllerContext context) { webAuth.PerformRedirect = authUrl => { HttpContext.Current.Response.Redirect(authUrl); }; Uri callback = webAuth.Callback == null ? HttpContext.Current.Request.Url : webAuth.Callback; webAuth.BeginAuthorization(callback); } } 

如果使用OutgoingWebresponse(没有升级dotnetOpenAuth但mvc是5)。

添加这个类(从langtu的回复中入侵):

  public class WrapperHttpResponseMessageResult : ActionResult { private readonly OutgoingWebResponse _response; public WrapperHttpResponseMessageResult(OutgoingWebResponse response) { _response = response; } public override void ExecuteResult(ControllerContext context) { HttpResponseBase responseContext = context.RequestContext.HttpContext.Response; responseContext.StatusCode = (int)_response.Status; responseContext.StatusDescription = _response.Status.ToString(); foreach (string key in _response.Headers.Keys) { responseContext.AddHeader(key, _response.Headers[key]); } if (_response.Body != null) { StreamWriter escritor = new StreamWriter(responseContext.OutputStream); escritor.WriteAsync(_response.Body).Wait(); } } } 

然后replace:

返回response.AsActionResult();

返回新的WrapperHttpResponseMessageResult(响应);