Использование IPrincipal в с MVC3 AuthorizationAttribute и избегание RoleProvider - PullRequest
0 голосов
/ 19 декабря 2011

У меня есть служба WCF, которая возвращает объект, который реализует как IPrinciple, так и IIdentity.

Я предполагал, что каким-то образом смогу подключить это к системе авторизации MVC3 без необходимости создания RoleProvider

например. так что я мог бы сделать что-то подобное в моем методе входа AccountController:

// AthenticatedUser implments both IPrinciple and IIdentity

AthenticatedUser user = wcfService.Logon(password, userName);
FormsAuthentication.SetAuthCookie(userName, false);

// Set IPrinciple so I can use IsInRole method elsewhere (or AuthorizationAttribute can reuse it)
this.HttpContext.User = authenticationClient.AuthenticatedUser;

Тогда каким-то волшебством, когда я использую

[Authorize (Roles = "foo", "bar")]

вызывается метод IsInRole моего AuthenticatedUser.

Однако в моем тестировании / отладке я обнаружил, что this.HttpContext.User, похоже, не поддерживается между запросами.

Редактировать извините: я должен был дать понять, что не хочу вызывать свою службу WCF при каждом запросе, я бы хотел как-то кэшировать / сохранить пользователя и роли и иметь возможность использовать AuthorizeAttribute с Принцип IP исходит от моего сервиса.

Кто-нибудь может помочь? Заранее спасибо!

Ответы [ 4 ]

3 голосов
/ 19 декабря 2011

Если вы используете IIS 7 для запуска этого на своем локальном компьютере, добавьте его в web.config в system.webServer:

<modules runAllManagedModulesForAllRequests="true">
    <remove name="FormsAuthentication" />
      <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
      <remove name="UrlAuthorization" />
      <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
      <remove name="DefaultAuthentication" />
      <add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
      <remove name="RoleManager" />
      <add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
</modules>
2 голосов
/ 19 декабря 2011

Вы говорите «this.HttpContext.User, кажется, не поддерживается между запросами» - это правильное поведение.Каждый запрос имеет уникальный HttpContext.

. Вы можете попробовать следующее:

FormsAuthentication.SetAuthCookie(userName, true);

, который создает долговременный файл cookie, который сохраняется между сеансами браузера.

http://msdn.microsoft.com/en-us/library/bk50ykcd.aspx

1 голос
/ 20 декабря 2011

Как вы выяснили, HttpContext не сохраняется в запросах и, следовательно, не IPrincipal и IIdentity - HttpContext создается в начале каждого запроса фреймворком, а IPrincipal и IIdentity созданы из билета аутентификации, десериализованного из куки-файла аутентификации.

То, что вы описываете, в некотором роде похоже на службу аутентификации WCF . В этом сценарии служба аутентифицирует пользователя и отправляет cookie-файл аутентификации в ответе вызывающему приложению, а затем приложение использует cookie-файл для построения IPrincipal и IIdentity для каждого последующего запроса.

Вы можете переопределить IPrincipal и IIdentity при возникновении события Application.PostAuthenticateRequest

protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
    if (Context.User != null)
    {
        var identity = Context.User.Identity;

        // define our own IIdentity and IPrincipal for an authenticated user
        if (identity.IsAuthenticated)
        {
            HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
            var ticket = FormsAuthentication.Decrypt(authCookie.Value);

            // get the roles from somewhere
            var roles = GetRoles(); 

            identity = new CustomIdentity(ticket.Name);
            IPrincipal principal = new CustomPrincipal(identity, roles);
            Context.User = Thread.CurrentPrincipal = principal;
        }
    }
}

Вы можете видеть, что роли должны быть получены откуда-то. При наличии RoleProvider эти роли могут быть кэшированы в другом файле cookie. Если вы знаете, что делаете с точки зрения безопасности, вы можете посмотреть на репликацию того, как роли сериализуются и шифруются в файле cookie.

Альтернативой может быть хранение ролей в сеансе, и их может быть достаточно для небольшого числа ролей. Помните, что сеанс недоступен до тех пор, пока не будет инициировано событие PostAcquireRequestState, некоторые события 7 позже в жизненном цикле запроса приложения , чем PostAuthenticateRequest.

0 голосов
/ 19 декабря 2011

В вашем глобальном asax можно отреагировать на событие AuthenticateRequest и изменить IIdentity следующим образом:

public class MvcApplication : System.Web.HttpApplication
{
    public override void Init()
    {
        base.Init();
        this.AuthenticateRequest += new EventHandler(MvcApplication_AuthenticateRequest);
    }

    void MvcApplication_AuthenticateRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.Request.IsAuthenticated)
        {
            var name = HttpContext.Current.User.Identity.Name;
            var key = "User-" + name;
            var principal = HttpContext.Current.Cache["User-" + name];
            if (principal == null)
            {
                principal = GetYourUserAsIPrincipal();
                // Add to cache for 1 hour with sliding expiration
                HttpContext.Current.Cache.Insert(key, principal, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0));
            }
            HttpContext.Current.User = principal ;
        }
    }        
}

РЕДАКТИРОВАТЬ : Для кэширования вы можете использовать стандартное кэширование ASP.NET. Я редактировал приведенный выше образец. Обратите внимание, что кэш ASP.NET является поточно-ориентированным (http://msdn.microsoft.com/en-us/library/system.web.caching.cache.aspx)

Было бы лучше, если бы вы объединили всю логику доступа к кешу в один класс.

Как и в случае с любым механизмом кэширования: если вы измените роли пользователей, это будет отражено только после истечения срока действия кэша.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...