Как настроить смешанные авторизации для разных аутентификаций в .net (веб-API 2 + owin)

Я новичок в .net, и я пытаюсь создать сервис restfull, в котором вы можете пройти аутентификацию через OAuth2 для такой службы, как facebook, а также иметь возможность войти в систему с «обычной учетной записью». Шаблон SPA от VS2013 позволил мне сделать это быстро и легко и я им очень доволен.

Сейчас я сталкиваюсь с другой проблемой. Кажется, я не могу найти способ разделить доступ для этих разных типов входа в систему. Например, я хочу разрешить только пользователям, использующим метод аутентификации oauth, доступ к X, а пользователям, прошедшим аутентификацию «обычным способом» (также с токеном носителя), — возможность видеть только Y.

Я искал в Интернете, и кажется, что я должен использовать тег [Authorize], но я не уверен, как его настроить и как различать разные логины. Я нашел различные методы настройки тега, но ни один из них не работает, и я постоянно натыкаюсь на устаревшие решения.

Кто-нибудь может помочь?

Благодарю вас!


Мое окончательное решение (спасибо 0leg)

Создал тег авторизации для каждого типа аутентификации:

public class AuthorizeExternalsOnly : AuthorizeAttribute
{
    protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
    {

        if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
        {
            string externalClaim = "";
            try
            {
                externalClaim = (actionContext.ControllerContext.RequestContext.Principal.Identity as ClaimsIdentity).Claims.FirstOrDefault(x => x.Type == ClaimTypes.Authentication).Value;
            }
            catch (NullReferenceException)
            {
                Debug.WriteLine("no external claim found");
            }
            if (externalClaim != "")
            {
               return base.IsAuthorized(actionContext);
            }
            return false;
        }
        return false;
    }
}

Затем в контроллере учетной записи я добавил утверждение в GetExternalLogin.

oAuthIdentity.AddClaim(new Claim(ClaimTypes.Authentication, "External"));
(...)
identity.AddClaim(new Claim(ClaimTypes.Authentication, "External"));

непосредственно перед каждым входом в систему.


person The one with doubts    schedule 21.04.2014    source источник
comment
Когда вы говорите доступ, вы имеете в виду авторизацию? Asp.net Identity поставляется с IdentityRole и другими реализациями. Вы можете разделять сторонние логины на нативные по ролям.   -  person Palak Bhansali    schedule 21.04.2014
comment
Да. В рассматриваемом проекте одни маршруты должны быть доступны только одному логину, а другие — другому. Моя проблема заключается в том, что в обоих случаях пользователь практически одинаков (единственное отличие состоит в том, как он прошел аутентификацию и получил токен доступа).   -  person The one with doubts    schedule 21.04.2014
comment
Решение будет работать. Хотя для уменьшения объема кода вы можете объединить два атрибута в один и передать в него параметр, указывающий, какой тип авторизации вы хотите. Например. [CustomAuthorizeAttribute("External")]   -  person 0leg    schedule 22.04.2014


Ответы (1)


Вы можете создать заявку, чтобы определить свой тип пользователя (внутренний, facebook и т. д.). Затем создайте собственный атрибут Authorize, чтобы принять решение об авторизации.

Посмотрите на это, эта и эта ссылки для некоторой справочной информации.

Пример кода для пользовательского атрибута авторизации. Параметр HttpActionContext позволяет увидеть, какой контроллер и какое действие вы вызвали. Это также позволяет вам проверять коллекцию утверждений для вашего пользователя. Пройдитесь по коду для разных сценариев входа, у вас будут разные претензии. Затем вы можете решить, авторизован ли ваш Controller.Action для определенного значения претензии.

protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
{
    ActionName = actionContext.ActionDescriptor.ActionName,
    ControllerName = actionContext.ControllerContext.ControllerDescriptor.ControllerName,
    Claims = (actionContext.RequestContext.Principal.Identity as ClaimsIdentity).Claims.ToList()
}
person 0leg    schedule 21.04.2014
comment
Привет, 0leg, спасибо за помощь, но у меня все те же проблемы... На данный момент я перезаписал функцию IsAuthorized из класса AuthorizeAttribute вместо функции Authorize. Это правильный способ сделать это? И с этого момента я понятия не имею, как проверить, какой метод используется для аутентификации. Я действительно не в курсе, и, кажется, так мало информации по теме... - person The one with doubts; 22.04.2014
comment
Да, вы правы, я добавил пример кода, показывающий, как переопределить IsAuthorized. - person 0leg; 22.04.2014
comment
Большое спасибо! Я только что добавил свое решение в исходный пост. Вероятно, не очень оптимизирован, но пока работает. - person The one with doubts; 22.04.2014