Erreur: le champ d'en-tête de la demande Content-Type n'est pas autorisé par Access-Control-Allow-Headers

102

J'ai créé un projet d'API Web mvc4 à l'aide de vS2012. J'ai utilisé le didacticiel suivant pour résoudre le partage de ressources Cross-Origin, "http://blogs.msdn.com/b/carlosfigueira/archive/2012/07/02/cors-support-in-asp-net-web-api- rc-version.aspx ". Cela fonctionne avec succès et je poste les données du côté client sur le serveur avec succès.

Après cela pour implémenter l'authentification dans mon projet, j'ai utilisé le tutoriel suivant pour implémenter OAuth2, "http://community.codesmithtools.com/CodeSmith_Community/b/tdupont/archive/2011/03/18/oauth-2-0-for -mvc-two-legged-implementation.aspx ". Cela m'aide à obtenir RequestToken côté client.

Mais quand je poste des données du côté client, j'ai l'erreur, "XMLHttpRequest ne peut pas charger http: //. Le champ d'en-tête de demande Content-Type n'est pas autorisé par Access-Control-Allow-Headers."

Mon code côté client ressemble à:

 function PostLogin() {
    var Emp = {};            
    Emp.UserName = $("#txtUserName").val();             
    var pass = $("#txtPassword").val();
    var hash = $.sha1(RequestToken + pass);
            $('#txtPassword').val(hash);
    Emp.Password= hash;
    Emp.RequestToken=RequestToken;
    var createurl = "http://localhost:54/api/Login";
    $.ajax({
        type: "POST",
        url: createurl,
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(Emp),
        statusCode: {
                200: function () {
                $("#txtmsg").val("done");                       
                toastr.success('Success.', '');                         
                }
                },
        error:
            function (res) {                        
                toastr.error('Error.', 'sorry either your username of password was incorrect.');            
                }
        });
    };

Mon contrôleur d'API ressemble à,

    [AllowAnonymous]
    [HttpPost]
    public LoginModelOAuth PostLogin([FromBody]LoginModelOAuth model)
    {
        var accessResponse = OAuthServiceBase.Instance.AccessToken(model.RequestToken, "User", model.Username, model.Password, model.RememberMe);

        if (!accessResponse.Success)
        {
            OAuthServiceBase.Instance.UnauthorizeToken(model.RequestToken);
            var requestResponse = OAuthServiceBase.Instance.RequestToken();

            model.ErrorMessage = "Invalid Credentials";

            return model;
        }
        else
        {
            // to do return accessResponse

            return model;
        }

    } 

Mon fichier webconfig ressemble à,

 <configuration>
   <configSections>   
   <section name="entityFramework"    type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  <section name="oauth" type="MillionNodes.Configuration.OAuthSection, MillionNodes, Version=1.0.0.0, Culture=neutral"/>
  <sectionGroup name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection, DotNetOpenAuth.Core">
  <section name="messaging" type="DotNetOpenAuth.Configuration.MessagingElement, DotNetOpenAuth.Core" requirePermission="false" allowLocation="true" />
  <section name="reporting" type="DotNetOpenAuth.Configuration.ReportingElement, DotNetOpenAuth.Core" requirePermission="false" allowLocation="true" />
</sectionGroup>
</configSections>
<oauth defaultProvider="DemoProvider" defaultService="DemoService">
<providers>
  <add name="DemoProvider" type="MillionNodes.OAuth.DemoProvider, MillionNodes" />
</providers>
<services>
  <add name="DemoService" type="MillionNodes.OAuth.DemoService, MillionNodes" />
</services>
</oauth>
<system.web>
 <httpModules>
   <add name="OAuthAuthentication" type="MillionNodes.Module.OAuthAuthenticationModule, MillionNodes, Version=1.0.0.0, Culture=neutral"/>
  </httpModules>
 <compilation debug="true" targetFramework="4.0" />
<authentication mode="Forms">
  <forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
<pages>
  <namespaces>
    <add namespace="System.Web.Helpers" />
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Optimization" />
    <add namespace="System.Web.Routing" />
    <add namespace="System.Web.WebPages" />
  </namespaces>
</pages>
</system.web>
<system.webServer>
 <validation validateIntegratedModeConfiguration="false" />      
  <modules>
      <add name="OAuthAuthentication"     type="MillionNodes.Module.OAuthAuthenticationModule, MillionNodes, Version=1.0.0.0, Culture=neutral" preCondition="" />
 </modules>
 <httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
  </httpProtocol>
</system.webServer>
<dotNetOpenAuth>
<messaging>
  <untrustedWebRequest>
    <whitelistHosts>
      <!-- Uncomment to enable communication with localhost (should generally not activate in production!) -->
      <!--<add name="localhost" />-->
    </whitelistHosts>
  </untrustedWebRequest>
</messaging>
<!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. -->
<reporting enabled="true" />

Kishore
la source
Jetez un œil à ce stackoverflow.com/questions/5027705/… et ajoutez une autre règle dans votre configuration Web
Mark Jones
Salut vous testez ce js directement à partir de votre navigateur et du système de fichiers local, par exemple file: // URL. ?? Et depuis quel navigateur?
Mark Jones

Réponses:

170

Comme l'indique ce message Erreur dans chrome: Content-Type n'est pas autorisé par Access-Control-Allow-Headers, ajoutez simplement l'en-tête supplémentaire à votre web.config comme ceci ...

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
  </customHeaders>
</httpProtocol>
Mark Jones
la source
Merci pour votre réponse. Il a essayé cela mais j'ai eu une erreur, "XMLHttpRequest ne peut pas charger localhost: 54 / api / Login . Origin null n'est pas autorisé par Access-Control-Allow-Origin."
Kishore le
Je n'ai toujours pas de chance avec cela, j'ai posté en détail ici: stackoverflow.com/questions/12437748/…
Kishore
112

Cela est probablement dû à une demande d'origine croisée , mais ce n'est peut-être pas le cas. Pour moi, j'avais débogué une API et l'avais défini Access-Control-Allow-Originsur *, mais il semble que les versions récentes de Chrome nécessitent un en-tête supplémentaire. Essayez d'ajouter ce qui suit à votre fichier si vous utilisez PHP:

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");

Assurez-vous que vous ne l'avez pas déjà utilisé headerdans un autre fichier, sinon vous obtiendrez une erreur désagréable. Consultez la documentation pour en savoir plus.

user1429980
la source
3
Pourquoi l'astérisque ne couvre-t-il pas tout - -;
user2483724
3
@ user2483724 c'est parce que l'astérisque autorise n'importe quel domaine d'origine, mais il ne spécifie pas les en-têtes supplémentaires autorisés. Il dit simplement: `` Vous pouvez appeler ce script à partir d'une page exécutée ailleurs ''
Garet Claborn
18

Je sais que c'est un vieux fil avec lequel j'ai travaillé la réponse ci-dessus et que j'ai dû ajouter:

header('Access-Control-Allow-Methods: GET, POST, PUT');

Donc, mon en-tête ressemble à:

header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
header('Access-Control-Allow-Methods: GET, POST, PUT');

Et le problème a été résolu.

Danny22
la source
10

Pour Nginx, la seule chose qui a fonctionné pour moi a été d'ajouter cet en-tête:

add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since';

Avec l'en-tête Access-Control-Allow-Origin:

add_header 'Access-Control-Allow-Origin' '*';

Ensuite, j'ai rechargé la configuration nginx et cela a très bien fonctionné. Crédit https://gist.github.com/algal/5480916 .

Nick Woodhams
la source