【问题标题】:Cross domain authentication of Web APIWeb API的跨域认证
【发布时间】:2014-02-21 07:58:20
【问题描述】:

我知道这是一个老问题,我已经阅读了很多关于它的文章,终于到了这里。无需身份验证(无需 [System.Web.Mvc.Authorize]),一切都可以正常工作:

  1. api 控制器:

    using System.Web.Http;
    using System.Web.Mvc;
    
    namespace WebApi.Controllers
    {
        [System.Web.Mvc.Authorize]
        public class ProductsController : ApiController
        {
            public IEnumerable<string> GetAllNames()
            {
                return new List<string> {"abc", "def", User.Identity.Name};
            }
    
            public string GetName(string name)
            {
                return name;
            }
        }
    }
    
  2. Web.Config 添加下面的四行以支持 CORS。

      <system.webServer>
        <validation validateIntegratedModeConfiguration="false" />
        <modules>
          <remove name="WebDAVModule"/><!-- ADD THIS to enable POST/DELETE -->
        </modules>
        <handlers>
          <remove name="WebDAV" /><!-- ADD THIS to enable POST/DELETE -->
          <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
          <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
          <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
          <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
          <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
          <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
        </handlers>
        <httpProtocol>
          <customHeaders>
            <clear />
            <!-- Adding the following custom HttpHeaders will help prevent CORS from stopping the Request-->
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
          </customHeaders>
        </httpProtocol>
      </system.webServer>
    

但是当 [Authorize] 被添加到 api 控制器时,一切都出错了。

这是调用 api 的页面,我从网上阅读了多达 7 个解决方案,如果其中任何一个有效,那将是一本教科书。很多人说“它对我有用”,但没有一个对我有用。

我将标题下的所有解决方案都注释掉了,并记录了它导致的错误。

        var host = 'http://localhost:54364/api/products/';
        userName = "name@domain.com";
        password = "password";
        $(document).ready(function () {
            //Solution 1: OPTIONS http://localhost:54364/api/products/GetAllNames?name=someone 405 (Method Not Allowed) / http://localhost:54364/api/products/GetAllNames?name=someone. Invalid HTTP status code 405  
            //$.ajaxSetup({
            //    headers: {
            //        'Authorization': "Basic " + btoa("cheny@cheny.com" + ":" + "nodenode")
            //    }
            //});
            $.ajax({
                type: "GET",
                url: host + "GetAllNames",
                dataType: 'json',
                //Solution 2: Ok, but User.Identity.UserName returns "", an empty string; I think it does not work at all.
                //username: userName,
                //password: password,
                async: false,
                //Solution 3: GET http://localhost:54364/api/products/GetAllNames?name=someone 405 (Method Not Allowed) / OPTIONS http://localhost:54364/api/products/GetAllNames?name=someone 405 (Method Not Allowed) / XMLHttpRequest cannot load http://localhost:54364/api/products/GetAllNames?name=someone. Invalid HTTP status code 405
                //headers: { "Authorization": btoa("Basic " + userName + ":" + password) },
                //Solution 4: XMLHttpRequest cannot load http://localhost:54364/api/products/GetAllNames. Wildcards cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:64710' is therefore not allowed access.
                //xhrFields: {
                //    withCredentials: true
                //},
                beforeSend: function (xhr) {
                    //Solution 5: Same with solution 2.
                    //xhr.withCredentials = true;
                    //Solution 6: OPTIONS http://localhost:54364/api/products/GetAllNames?name=someone 405 (Method Not Allowed) / OPTIONS http://localhost:54364/api/products/GetAllNames?name=someone 405 (Method Not Allowed)  / XMLHttpRequest cannot load http://localhost:54364/api/products/GetAllNames?name=someone. Invalid HTTP status code 405 
                    //xhr.setRequestHeader("Authorization", "Basic " + btoa(userName + ":" + password));
                    //Solution 7 ( 5 + 6 ): same with solution 6.
                },
                crossDomain: true,
                success:
                    function(data) {
                        // On success, 'data' contains a list of products.
                        $.each(data, function(key, item) {
                            // Add a list item for the product.
                            $('<li>', { text: formatItem(item) }).appendTo($('#ajax'));
                        });
                    }
            });

刚接触 ajax 和 web api(只有 2 天的经验),我想我可能错过了一些东西,例如,解决方案 4 没有用户名/密码信息,它怎么能工作?

提前致谢,欢迎任何 cmets。

【问题讨论】:

    标签: ajax authentication cross-domain asp.net-web-api


    【解决方案1】:

    问题出在您回复的 Access-Control-Allow-Origin 标头中。如果您使用身份验证,则不能使用通配符*。您需要明确设置域。

    如果您想使用withCredentials: true,那么您的服务器必须将额外的标头Access-Control-Allow-Credentials设置为true

    Access-Control-Allow-Credentials: true
    

    【讨论】:

    • 感谢您的回答。由于我现在没有进行此测试,因此我将就稍后发生的情况提供反馈:)
    猜你喜欢
    • 2013-06-06
    • 2017-01-14
    • 2010-11-06
    • 2014-03-01
    • 2012-06-01
    • 2021-11-24
    相关资源
    最近更新 更多