#servicestack
#servicestack
Вопрос:
В настоящее время я немного борюсь со своей пользовательской CredentialsAuthProvider
реализацией. Сначала важно сказать, что я пишу клиент WPF в качестве ссылки для моего API.
- Браузер хранит файлы cookie, и вы можете настроить, как с ними обращаться, например, удалять при закрытии браузера. На рабочем столе Windows у вас есть среда.Специальная папка.Файлы cookie, в которых Windows хранит файлы cookie. Но я ничего не смог найти из ServiceStack. Так он ничего не хранит в настольном приложении Windows? Я видел, что есть
client.CookieContainer
место, где я нахожу три файла cookie после входа в систему. - Могу ли я каким-либо образом добавить свойства к этому файлу cookie во время аутентификации? Если да, то как? В настоящее время я использую
AuthenticationResponse.Meta
словарь для передачи дополнительной информации:public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request) { var authResponse = (AuthenticateResponse)base.Authenticate(authService, session, request); authResponse.Meta = new Dictionary<string, string>(); authResponse.Meta.Add("Test", "TestValue"); return authResponse; }
- И, наконец: является ли экземпляр моего производного
CredentialsAuthProvider
класса потокобезопасным? ВTryAuthenticate(...)
я устанавливаю соединение с БД и извлекаю объект, который содержит всю информацию, включая хэшированный пароль и т.д. Но я могу только заполнить эту информацию для объекта сеансаOnAuthenticated(....)
и / или переопределитьAuthenticate(...)
. Если возможно, я не хочу делать еще один вызов DB для повторного получения того же объекта. Так безопасно ли объявлять элементuser
, заполнять егоTryAuthenticate
и повторно использовать в других перезаписанных методах, например:public class BediCredentialsAuthProvider : CredentialsAuthProvider { private AppUser user = null; public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request) { var authResponse = (AuthenticateResponse)base.Authenticate(authService, session, request); authResponse.Meta = new Dictionary<string, string>(); authResponse.Meta.Add("ValueA", user.ValueA); // ... add more properties from user object return authResponse; } public override bool TryAuthenticate(IServiceBase authService, string userName, string password) { AppUser user = null; using (var session = NhSessionFactories.OpenSession(TopinConstants.TopInDbFactory)) { using (var transaction = session.BeginTransaction()) { try { var appUserRepo = new AccountManagementRepository(session); user = appUserRepo.GetAppUser(userName); // get user from database using NHibernate transaction.Commit(); session.Close(); } catch (Exception ex) { Log.Error($"Error retrieving user {user} to authenticate. Error: {ex}"); throw; } } } // do some logic to test passed credentials and return true or false } public override IHttpResult OnAuthenticated(IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo) { session.DisplayName = user.DisplayName; session.FirstName = user.Firstname; session.LastName = user.Lastname; session.Email = user.EmailAddress; // etc..... return base.OnAuthenticated(authService, session, tokens, authInfo); } }
Ответ №1:
Вы можете заполнять файлы cookie клиента сервиса ServiceStack точно так же, как в браузере, за исключением того, что он сохраняет только постоянные идентификаторы сеанса, с помощью которых вам нужно будет проходить аутентификацию RememberMe=true
, например:
var response = client.Post(new Authenticate {
provider = "credentials",
UserName = ...,
Password = ...,
RememberMe = true,
});
Который сохранит сеанс аутентифицированного пользователя в ss-pid
постоянном файле cookie в контейнере CookieContainer HttpWebRequest и будет отправляться при каждом последующем запросе.
Вы можете установить свои собственные постоянные файлы cookie в OnAuthenticated
from authService
с помощью:
var httpRes = authService.Request.Response;
httpRes.SetPermanentCookie(cookieName, cookieValue);
Является ли экземпляр моего производного класса CredentialsAuthProvider потокобезопасным?
Нет, для аутентификации каждого запроса используется один и тот же экземпляр AuthProvider singleton, поэтому вы не можете поддерживать какие-либо сохраненные переменные в самом экземпляре и должны будете удалить:
//private AppUser user = null; //Instance variables are not ThreadSafe
Если вы хотите передавать элементы и получать к ним доступ по всему конвейеру запросов, вы можете сохранить их в IRequest.Items
словаре, например:
authService.Request.Items["AppUser"] = user;