37 votes

DotNetOpenAuth ne fonctionne pas avec MVC 5 RC

J'ai beaucoup travaillé avec DotNetOpenAuth. Nous avons d'abord utilisé la version 5.0.0-alpha1 mais nous sommes passés à la version 4.0.30319 parce que nous n'arrivions pas à trouver ce qui causait nos problèmes.

Nous construisons un projet API Web C# sur .NET 4.5.1 RC avec MVC 5 RC dans Visual Studio 2013. Nous avons implémenté IAuthorizationServerHost , INonceStore et ICryptoKeyStore .

Le problème que nous rencontrons se situe dans le cas suivant :

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(); une méthode qui trouve son origine dans DotNetOpenAuth.Messaging et le MessagingUtilities classe statique. Le site DotNetOpenAuth.Core (qui contient ce code) fait référence à MVC 4.0 et aux HttpResponseMessageActionResult hérite de la classe ActionResult .

Cela signifie que la version actuelle de DotNetOpenAuth n'est pas compatible avec MVC 5. Compiler et essayer de l'exécuter ne fera que provoquer des erreurs 500.

Quelqu'un a-t-il une idée de la façon dont cela pourrait être facilement corrigé (ou peut-être pas) ?

Je n'avais pas remarqué que le paquet Nuget DotNetOpenAuth avait écrasé mes paquets pour 5.0. Donc, après avoir réinstallé les paquets et ajouté le assemblyBinding à nouveau :

<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>

Cela nous a permis d'avancer un peu. Maintenant, l'erreur se résume à :

La tentative de la méthode transparente de sécurité 'DotNetOpenAuth.Messaging.MessagingUtilities.AsActionResult(DotNetOpenAuth.Messaging.OutgoingWebResponse)' d'accéder au type critique de sécurité 'System.Web.Mvc.ActionResult' a échoué.

50voto

Andrew Arnott Points 35346

Correction disponible.

Installez le paquet NuGet DotNetOpenAuth.Mvc5 et changez toutes les utilisations de AsActionResult() à AsActionResultMvc5()

6voto

jens Points 176

Après un débogage plus poussé et une discussion avec les personnes de DotNetOpenAuth sur GitHub. https://github.com/DotNetOpenAuth/DotNetOpenAuth/issues/307 la conclusion est que MVC 5 a un nouveau modèle de sécurité.

Une redirection contraignante ne sera donc pas suffisante. Jusqu'à nouvel ordre, il y a deux possibilités :

1) Prenez le code source de DotNetOpenAuth et supprimez l'[assembly : AllowPartiallyTrustedCallers] de tous les projets. Recompiler et membre pour désactiver la vérification du nom fort sn -Vr *. Après ce code ne peut pas être exécuté sur les environnements Medium Trust.

2) Récupérer le code source de DotNetOpenAuth et le recompiler contre MVC 5.

Selon la discussion sur GitHub, la meilleure solution pour l'avenir serait de déplacer tous les éléments MVC connexes vers une assemblée distincte.

3voto

langtu Points 480

Une solution de contournement (utilisable avec le paquet nuget beta actuel) pour ce cas :

  • Créer une classe ActionResult enveloppant 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();
            }
        }
    }
  • Changement return outgoingWebResponse.AsActionResult(); à new WrapperHttpResponseMessageResult(outgoingWebResponse);

Code de WrapperHttpResponseMessageResult est copié à partir de AsActionResult Ils remplissent donc la même fonction.

2voto

Lightwalker Points 329

Utilisez ceci pour vous assurer que l'autorisateur est passé correctement.

  public class MvcAuthorizer : WebAuthorizer
{
    public ActionResult BeginAuthorization()
    {
        return new MvcOAuthActionResult(this);
    }

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

' puis le récupérer correctement

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);
    }
}

0voto

Si vous l'utilisez avec OutgoingWebresponse (je n'ai pas mis à jour dotnetOpenAuth mais mvc oui à 5).

Ajoutez cette classe (tirée de langtu (réponse de l'entreprise) :

 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();
        }
    }
}

Et ensuite remplacer :

retourner la réponse.AsActionResult() ;

avec

retourner un nouveau WrapperHttpResponseMessageResult(response) ;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X