Servicestack — НЕАВТОРИЗОВАННЫЙ после успешного входа в систему

#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); } Похоже, теперь работает. Требуется дополнительное тестирование. Имеет ли это смысл??