Несколько поддоменов FormsAuthentication не работают, используя Web API MVC 4

Я делаю проект, которому нужен веб-сайт и мобильное приложение, почти с одинаковой функциональностью. Поэтому для этого я создаю API с использованием Asp.net Web API, который также будет использоваться на веб-сайте и в мобильном приложении.

Адрес API: api.domain.com Адрес веб-сайта: testing.domain.com

Проблема:

Теперь на api.domain.com я разрешаю пользователю войти в систему, там используется FormsAuthentication с Cookies.

Когда пользователь проходит аутентификацию, он получает 200 Http Satus вместе с заголовком Set-Cookie, где также упоминаются разрешенные домены.

Вот запрос и ответ:

**Request**

Request URL:http://api.domain.com/account/login
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:139
Content-Type:application/x-www-form-urlencoded
Host:api.domain.com
Origin:http://testing.domain.com
Referer:http://testing.domain.com/Login.aspx?ReturnUrl=%2fteacherpanel
User-Agent:Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1
Form Dataview URL encoded
__VIEWSTATE:/wEPDwUKMTY1NDU2MTA1MmRkmpJ4YQ4kteUpklwLOmcHppPgq/RHqfw7tilyk8pJp0Y=
UserName:ishan
Password:pass





**Response**

Access-Control-Allow-Headers:Content-Type
Access-Control-Allow-Methods:PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Origin:*
Cache-Control:no-cache
Content-Length:0
Date:Sat, 22 Sep 2012 10:23:38 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/7.5
Set-Cookie:.Teacher=A3BD94D26CF733F6F223198ADE40D87C76D8ECC663D7CEDD6E3FF18B0ED23032F6089EF24141E0B65F3F29503A3AC1670C92B9CE4EF7D986974ABE61AB5F0C837245D1A30A8D8E8E058F9AFDD89281CBAB9A3EB98B4A320E689718AF9E76E4911506EBA7FD4244336D8409CFB6D77B179764726B550AB0FFF7A6508658615A57; domain=domain.com, .domain.com; path=/; HttpOnly
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET

Теперь, в соответствии с ответом, браузер должен отправлять этот файл cookie на сервер с каждым запросом к этому домену domain.com или любому его поддомену.

Но этого не происходит, как бы сегодня утром это ни работало для меня, но я не знаю, что произошло после того, как я опубликовал.

Также для получения дополнительной информации здесь приведен код, который я использую для установки cookie и проверки того, вошел ли пользователь в систему.

Здесь, чтобы войти в систему, эта проверка выполняется в API по адресу api.domain.com.

[AllowAnonymous]
        [HttpPost]
        public HttpResponseMessage Login(LoginModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                Teacher t;
                if (Teacher.Login(model.UserName,model.Password,out t))
                {
                   // Roles.AddUserToRole(t.ID.ToString(), "teacher");

                    FormsAuthentication.SetAuthCookie(t.ID.ToString(), model.RememberMe);






                    FormsAuthenticationTicket ft = new FormsAuthenticationTicket(
                     1,                                   // version
                     t.ID.ToString(),   // get username  from the form
                     DateTime.Now,                        // issue time is now
                     DateTime.Now.AddMinutes(30),         // expires in 10 minutes
                     true,      // cookie is not persistent
                     "teacher"                              // role assignment is stored
                        // in userData
                     );

                    string enTicket = FormsAuthentication.Encrypt(ft);


                    HttpResponseMessage res = Request.CreateResponse(HttpStatusCode.OK);


                    System.Net.Http.Headers.CookieHeaderValue cokie = new System.Net.Http.Headers.CookieHeaderValue(FormsAuthentication.FormsCookieName, enTicket);
                    cokie.Domain = "domain.com  .domain.com";
                    IEnumerable<System.Net.Http.Headers.CookieHeaderValue> cookies = new System.Net.Http.Headers.CookieHeaderValue[] { cokie };

                    res.Headers.AddCookies(cookies);


                    return res;

                }
                return Request.CreateResponse(HttpStatusCode.Unauthorized);
            }

            // If we got this far, something failed, redisplay form
            return Request.CreateResponse(HttpStatusCode.Unauthorized);
        }

Теперь на testing.domain.com, просто проверяя аутентификацию пользователя в соответствии с его ролью, на web.config.

<location path="TeacherPanel">
    <system.web>
      <authorization>
        <allow roles="teacher" />
        <deny users="?" />
      </authorization>
    </system.web>
  </location>

Это детали, которые я нашел проверенными, исследуя эту проблему. Не стесняйтесь предлагать любую вещь, каждая подсказка будет полезна.

Раздел аутентификации в веб-конфигурации testing.domain.com

 <authentication mode="Forms">
      <forms name=".Teacher" loginUrl="Login.aspx" protection="All" path="/" timeout="30" domain=".domain.com" />
    </authentication>

Раздел аутентификации в веб-конфигурации api.domain.com

 <authentication mode="Forms">
  <forms  name=".Teacher"
    cookieless="UseCookies"
    requireSSL="false"
     domain=".domain.com"
     />
</authentication>

После добавления ключа машины и добавления срока действия в файл cookie

Отправить запрос браузера на аутентификацию:

POST /account/login HTTP/1.1
Host: api.domain.com
Connection: keep-alive
Content-Length: 123
Origin: http://testing.domain.com
User-Agent: Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1
Content-Type: application/x-www-form-urlencoded
Accept: */*
Referer: http://testing.domain.com/TeacherLogin.aspx?ReturnUrl=%2fteacherpanel
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

__VIEWSTATE:/wEPDwUKMTY1NDU2MTA1MmRkCjMwS9YdCRDD3Qsd4GYnLj+tGGg=
UserName:username
Password:pass

Ответ, отправленный сервером:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/7.5
Set-Cookie: .Teacher=9C8FD43FABDC1817D21272361CBF798BB64C364DECC62E2F5F666D1B2A248076C67737D89B03F515D4D81524345584B11E206B2DDEAD5AA846A15BC17B32D86DF1C95A2943766AB5955C99A8DD0D5984089131838E158A90241B60D40A2D928086486E2BA3DDE95814E7FA303845FBDE235D69F54B6891852A09A80F7465FF8C59957A4D; expires=Wed, 26 Sep 2012 10:02:46 GMT; max-age=432000; domain=.domain.com; path=/; secure; httponly
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
Date: Tue, 25 Sep 2012 10:02:46 GMT
Content-Length: 0

Следующий запрос на получение, отправленный на testing.domain.com для тестирования (что не удается, поскольку браузер не отправляет файлы cookie обратно на сервер):

GET / HTTP/1.1
Host: testing.domain.com
Connection: keep-alive
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1
Accept: */*
Referer: http://testing.domain.com/TeacherLogin.aspx?ReturnUrl=%2fteacherpanel
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

Есть предположения, почему браузер не отправляет файлы cookie обратно?


person Ishan Dhingra    schedule 22.09.2012    source источник
comment
Можете ли вы также опубликовать раздел ‹аутентификации›‹форм› вашего web.config? И у API, и у тестирования есть файл web.config? И если да, то убедились ли вы, что машинный ключ совпадает?   -  person explunit    schedule 22.09.2012
comment
Только что добавили раздел ‹аутентификация›, но не знаете, где найти и куда вставить ключ машины?   -  person Ishan Dhingra    schedule 22.09.2012
comment
добавлен машинный ключ, чтобы ответить ниже   -  person explunit    schedule 22.09.2012
comment
Убедитесь, что у вас нет файла преобразования отладки web.config, который изменяет ваши значения.   -  person David d C e Freitas    schedule 19.03.2014


Ответы (1)


Здесь могут происходить две вещи:

  1. Если у вас нет машинного ключа как в API, так и в тестовом web.config, возможно, вы используете унаследованные настройки из .Net Framework machine.config или web.config. Это будет генерировать разные ключи для каждого приложения, поэтому файл cookie, выданный в одном, не может быть расшифрован другим. Вы должны добавить тот же раздел machinekey к каждому web.config. Вы можете использовать один из множества онлайн-генераторов, например этот.

  2. Другая проблема связана с попыткой поместить несколько доменов в один файл cookie. Измените эту строку:

    cokie.Domain = "domain.com .domain.com";

К этому:

cokie.Domain = ".domain.com";

На самом деле, глядя на ваши разделы, вам может даже не понадобиться эта строка, поскольку оба они настроены на выдачу cookie на .domain.com.

РЕДАКТИРОВАТЬ: также проверьте раздел http://msdn.microsoft.com/en-us/library/ms228262%28v=vs.90%29.aspx. вашего web.config, чтобы контролировать, отправляются ли файлы cookie с установленным безопасным флагом. Например, в среде разработки вы хотите отключить безопасный флаг:

<httpCookies httpOnlyCookies="true" requireSSL="false" />

Существует также свойство forms requireSSL, но я не думаю, что это применимо в вашем случае, потому что вы вручную выдаете файл cookie.

person explunit    schedule 22.09.2012
comment
Только что сделал трюк с машинным ключом, но не работает ... Проблема в том, что когда браузер получает файлы cookie, он должен отправить их со следующим запросом, но здесь он просто не отправляет их. Кажется, чего-то не хватает, что мешает браузеру отправить файл cookie со следующим запросом. - person Ishan Dhingra; 22.09.2012
comment
исходный вопрос имеет запрос/ответ, но можете ли вы опубликовать, как он выглядит сейчас после изменения вашего кода/конфигурации? Также следующий запрос после исходного ответа (тот, который не отправляет файлы cookie)? - person explunit; 22.09.2012
comment
Только что подобрался очень близко к решению, проблема в том, что поле «истечение» файла cookie не установлено, есть ли у вас какие-либо идеи, почему сервер не отправляет файл cookie с установленным временем истечения срока действия ?? это IIS7. - person Ishan Dhingra; 25.09.2012
comment
Похоже, что срок действия файла cookie истек. Однако я вижу, что для файла cookie установлен безопасный флаг, но последующий запрос - это просто HTTP. Возможно, поэтому cookie не отправляется. - person explunit; 25.09.2012
comment
Я просто добавил безопасный в качестве эксперимента, после этого я его удалил, и он не работает в обоих направлениях. Я исследовал и где-то нашел подсказку, что эта проблема может быть из-за заголовка Cache-Control, когда я сравнил этот ответ с тем, который был сделан, когда мы используем FormsAuthentication на обычном веб-сайте. Обычный веб-сайт имеет Cache-Control:private, no-cache=set-cookie. но здесь это Cache-Control: no-cache. Мне кажется, это проблема. Как вы думаете, у вас есть какое-нибудь представление о заголовке Cache-Control? - person Ishan Dhingra; 26.09.2012