2015-02-10 6 views
0

Я использую ServiceStack v4 с пользовательской аутентификацией. Это настройка и правильная работа. Я могу вызвать службу/auth и получить возвращенный запрос AuthorizationResponse с уникальным SessionId.сеанс пользователя ServiceStack не найден при использовании sessionId в клиенте Заголовки или файлы cookie

У меня также есть плагин smagger-ui setup. Используя его, я могу выполнить аутентификацию через/auth, а затем вызвать одну из моих других служб, для которой требуется аутентификация без проблем.

Теперь, из вторичного приложения MVC, использующего C# JsonServiceClient, я снова могу успешно выполнить вызов/auth, а затем защищенные службы, используя один и тот же объект-клиент. Однако, если я распоряжаюсь этим клиентом (после сохранения уникального sessionId в файл cookie), затем создайте новый клиент и добавьте sessionId в виде файла cookie или через заголовки, используя x-ss-pid, как описано, вызовы возвращаются 401. Если я вызываю небезопасную службу, но затем попытаюсь получить доступ к уникальному сеансу пользователя, он вернет новый сеанс.

Если я смотрю заголовки запроса в этой службе, cookie или заголовок четко задаются с помощью sessionId. SessionId также существует в sessionCache. Проблема заключается в том, что код, который пытается получить сеанс от запроса, не находит его.

Чтобы быть более конкретным, представляется, что ServiceExtensions.GetSessionId рассматривает HostContext, а не вызывающий запрос. Я не знаю, почему. Возможно, я неправильно понимаю что-то на этом пути.

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

var req = base.Request; 
    var sessionId = req.GetHeader("X-" + SessionFeature.PermanentSessionId); 

    var sessionKey = SessionFeature.GetSessionKey(sessionId); 
    var session = (sessionKey != null ? Cache.Get<IAuthSession>(sessionKey) : null)?? SessionFeature.CreateNewSession(req, sessionId); 

Итак, я пропустил что-то очевидное здесь? Или, может быть, не так очевидно при создании моего вторичного клиента?

Пример кода клиента вызывает

Вот мой код авторизации. Он содержится в классе контроллера. Это только соответствующие части.

using (var client = new JsonServiceClient(WebHelper.BuildApiUrl(Request))) 
{ 
    try 
    { 
     loginResult = client.Post(new Authenticate() 
         { 
          UserName = model.Email, 
          Password = model.Password, 
          RememberMe = model.RememberMe 
         }); 

     Response.SetCookie(new HttpCookie(SessionFeature.PermanentSessionId, loginResult.SessionId)); 

     return true; 
    } 
} 

Вот мой вторичные установки клиента и служба вызова, содержащийся в его собственном классе контроллера в другой области приложения MVC

using (var client = new JsonServiceClient(WebHelper.BuildApiUrl(Request))) 
{ 
    var cCookie = HttpContext.Request.Cookies.Get(SessionFeature.PermanentSessionId); 
    if (cCookie != null) 
    { 
     client.Headers.Add("X-" + SessionFeature.PermanentSessionId, cCookie.Value); 
     client.Headers.Add("X-" + SessionFeature.SessionOptionsKey, "perm"); 

    } 

    response = client.Get(new SubscriptionStatusRequest()); 
} 

Дополнительного обновление

В Authenticate процесс вызывается из HttpRequestExtensions с именем = SessionFeature.PermanentSessionId

public static class HttpRequestExtensions 
{ 
    /// <summary> 
    /// Gets string value from Items[name] then Cookies[name] if exists. 
    /// Useful when *first* setting the users response cookie in the request filter. 
    /// To access the value for this initial request you need to set it in Items[]. 
    /// </summary> 
    /// <returns>string value or null if it doesn't exist</returns> 
    public static string GetItemOrCookie(this IRequest httpReq, string name) 
    { 
     object value; 
     if (httpReq.Items.TryGetValue(name, out value)) return value.ToString(); 

     Cookie cookie; 
     if (httpReq.Cookies.TryGetValue(name, out cookie)) return cookie.Value; 

     return null; 
    } 

Теперь, что происходит, это httpReq.Items содержит значение SessionFeature.PermanentSessionId, но я не знаю, почему и где это устанавливается. Я даже не понимаю в этот момент, что контейнер Items находится на IRequest. Таким образом, код никогда не попадает в функции проверки моих файлов cookie или заголовков

ответ

2

Session wiki описывает различные файлы cookie, используемые SessionStack Session.

Если клиент хочет использовать постоянный SessionId (т. Е. ss-pid), ему также необходимо отправить cookie ss-opt=perm, чтобы указать, что он хочет использовать постоянную сессию.Это Cookie автоматически устанавливается при аутентификации с помощью опции RememberMe=true во время аутентификации.

В сеансе RequestFilter возникла проблема, которая использовалась для обеспечения присоединения идентификаторов сеанса к текущему запросу, не используя общедоступный API IRequest.GetPermanentSessionId(), который также ищет SessionIds в заголовках HTTP. Эта проблема была решена with this commit которая теперь позволяет выполнять запросы сеансов с использованием HTTP-заголовков, например:

//First Authenticate to setup an Authenticated Session with the Server 
var client = new JsonServiceClient(BaseUrl); 
var authResponse = client.Send(new Authenticate 
{ 
    provider = CredentialsAuthProvider.Name, 
    UserName = "user", 
    Password = "[email protected]", 
    RememberMe = true, 
}); 

//Use new Client instance without Session Cookies populated 
var clientWithHeaders = new JsonServiceClient(BaseUrl); 
clientWithHeaders.Headers["X-ss-pid"] = authResponse.SessionId; 
clientWithHeaders.Headers["X-ss-opt"] = "perm"; 

var response = clientWithHeaders.Send(new AuthOnly()); //success 

Это исправление доступно из v4.0.37 +, что теперь available on MyGet.

+0

Интересно. Сейчас я попробую попробовать (включая дополнительный opt = perm). Для меня документация не обязательно ясна. Лучший ответ, который я нашел на сегодняшний день, также не включал эту потребность. [Ссылка] (http://stackoverflow.com/questions/19160839/reconnecting-to-servicestack-session-in-an-asp-net-mvc4-application). Я скоро вернусь к своим результатам. – tracstarr

+0

Это не имело значения. Я попытался использовать оба заголовка и куки, добавляя дополнительный ss-opt. Я уточню свой вопрос с дополнительным примером кода вызовов. – tracstarr

+0

@tracstarr FYI исправил проблему с переопределением SessionIds, пример выше теперь работает с v4.0.37 +, это [доступно на MyGet] (https://github.com/ServiceStack/ServiceStack/wiki/MyGet). – mythz

1

Однако, если избавиться от этого клиента (после сохранения уникального SESSIONID в печенье)

Если клиент расположен где куки вы спасаете SESSIONID расположены? Этот answer может предоставить дополнительную информацию.

потом создать новый клиент, и либо добавить SESSIONID как Cookie или через заголовки с помощью х-сс-PID, как документировано, вызов службы возвращает 401

Если хранить/сохранить действующий SESSIONID как строку, вы должны быть в состоянии предоставить ее в CookieContainer нового клиента (учитывая, что sessionId все еще аутентифицирован). Я знаю, что вы сказали, что попытался добавить SESSIONID как Cookie, но я не образец см в ваш вопрос, используя CookieContainer таким образом это должно выглядеть примерно так ...

using (var client = new JsonServiceClient(WebHelper.BuildApiUrl(Request))) 
{ 
    var cCookieId = savedCookieId; //a string that I believe you saved from a successfully authenticated client that is now disposed 
    if (cCookieId != null) 
    { 
     var cookie = new Cookie(SessionFeature.PermanentSessionId, cCookieId); 
     //cookie.Domian = "somedomain.com" //you will probably need to supply this as well 
     client.CookieContainer.Add(cookie) 
    } 

    response = client.Get(new SubscriptionStatusRequest()); 
} 
+0

Итак, вы правы в моем примере выше. Я не сохраняю конкретный файл cookie, возвращенный клиентом, но sessionId. Согласно документам, это все, что нужно - особенно если вы используете заголовки вместо файлов cookie в последующем новом запросе клиента. Я также сделал то же, что и в вашем примере кода с таким же результатом. Я потратил некоторое время, пытаясь отладить все дальше. Я обнаружил, что метод HttpRequestExtensions.GetItemOrCookie получает вызов в поисках значения ss-pid в контейнере IRequest.Items. Он находит один и возвращает его (но это не тот, который я хочу.) – tracstarr

+0

Проблема теперь в том, что я не знаю, что, как и почему этот контейнер Items содержит sessionId и почему он выбирается при просмотре файлов cookie или заголовков , – tracstarr

Смежные вопросы