#servicestack
#servicestack
Вопрос:
Должно быть, я что-то пропустил, но я получаю несанкционированные ошибки для операций, которые аннотируются [Authorize]
ПОСЛЕ успешного входа в систему. Я попробовал аннотацию на нескольких уровнях: класс обслуживания, RequestDTOs, а также отдельные методы моего класса обслуживания. Поведение всегда одно и то же.
Я создал свой собственный AuthProvider, производный от CredentialsAuthProvider
. Я НЕ использую ORMLite, я использую NHibernate 4. Мой клиент — приложение WPF. Мой метод AppHost.Configure() выглядит следующим образом:
public override void Configure(Container container)
{
//Config examples
//this.Plugins.Add(new PostmanFeature());
//this.Plugins.Add(new CorsFeature());
Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[]
{
new BediCredentialsAuthProvider(),
}
));
Plugins.Add(new ValidationFeature());
container.RegisterValidators(typeof(AppUserValidator).Assembly);
container.RegisterAs<BediAuthEvents, IAuthEvents>();
container.Register<ICacheClient>(new MemoryCacheClient());
}
И затем я замечаю другое странное (для меня) поведение: я реализовал пользовательские события аутентификации для OnAuthenticated()
and OnLogout
. Я пишу запись в журнале в обоих случаях. Я использую свойство session.UserAuthName
в обоих случаях. В OnAuthenticated()
этом свойстве заполнено правильно. После вызова операции, в которой я получил несанкционированную ошибку OnLogout
, метод не может ссылаться на session.UserAuthName
свойство, поскольку оно равно null.
Есть идеи, что здесь не так? Кажется, что-то не так с моими сеансами, но я понятия не имею, что!
Обновление сообщения
Извините, я неправильно ввел свою аннотацию. Я использую [Authenticate]
и нет [Authorize]
! Вот пример из моего класса обслуживания:
[Authenticate]
public object Post(CreateAppUser request)
{ .... }
[Authenticate]
public object Put(UpdateAppUser request)
{ .... }
2-е обновление
Вот код из моего AuthProvider:
public class BediCredentialsAuthProvider : CredentialsAuthProvider
{
public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
{
var authResponse = (AuthenticateResponse)base.Authenticate(authService, session, request);
var user = (AppUser)authService.Request.Items["AppUser"];
authResponse.Meta = new Dictionary<string, string>();
authResponse.Meta.Add("TenantName", user.TenantName);
authResponse.Meta.Add("ResetPwdRequired", user.MustChangePwd.ToString());
authResponse.Meta.Add("IsLockedOut", user.IsLockedOut.ToString());
authResponse.Meta.Add("Email", user.EmailAddress);
authResponse.Meta.Add("DisplayName", user.DisplayName);
authResponse.Meta.Add("RemoteIP", authService.Request.RemoteIp);
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);
transaction.Commit();
session.Close();
}
catch (Exception ex)
{
Log.Error($"Error retrieving user {user} to authenticate. Error: {ex}");
throw;
}
}
}
if (user == null)
throw HttpError.NotFound("User '{0}' not found. Please try again.".Fmt(userName));
authService.Request.Items.Add("AppUser", user);
var pwdMgr = new PwdManager();
var hpwd = pwdMgr.GetHashedPassword(password, user.Salt);
return hpwd == user.Password;
}
}
Ответ №1:
Атрибут фильтра запроса ServiceStack для проверки подлинности пользователя, имеющего доступ к вызову службы, является атрибутом [Authenticate]. [Authorize]
Не связанный атрибут MVC предназначен для использования только в MVC, не имеющий отношения к аутентификации ServiceStack.
Комментарии:
1. Извините, я неправильно ввел свое сообщение! Я исправил это, обновив его.
2. @tommyb хорошо, но невозможно определить, в чем проблема, только из этого описания, я предполагаю, что это в вашем пользовательском AuthProvider impl. Обратите внимание, что вам не нужно регистрироваться
MemoryCacheClient
, это уже по умолчанию.UserAuthName
Заполняется ли CacheClient после аутентификации?3. Я снова обновил сообщение и добавил код для моего AuthProvider. Я зарегистрировал MemoryCacheClient во время поиска проблемы, потому что думал, что она отсутствует….
4. @tommyb Можете ли вы опубликовать необработанный HTTP-запрос / ответы как на запрос успешной аутентификации, так и на запрос неудачной аутентификации, вы можете использовать что-то вроде Fiddler для захвата необработанных HTTP-заголовков.
5. Думаю, я сам это понял. Я добавил в свой AuthProvider следующее: `общедоступное переопределение IHttpResult OnAuthenticated(IServiceBase AuthService, сеанс IAuthSession, токены IAuthTokens, Dictionary<string, string> AuthInfo) { возвращает базу. OnAuthenticated(AuthService, session, tokens, AuthInfo); } Похоже, теперь работает. Требуется дополнительное тестирование. Имеет ли это смысл??