asp mvc 3 ActionFilter для базовой аутентификации - PullRequest
5 голосов
/ 22 февраля 2012

У меня есть служба отдыха ASP MVC3, которая использует базовую аутентификацию.После поиска переполнения стека я создал следующий код.

public class BasicAuthentication : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var req = filterContext.HttpContext.Request;
        if (String.IsNullOrEmpty(req.Headers["Authorization"]))
        {
            filterContext.Result = new HttpNotFoundResult();
        }
        else
        {
            var credentials = System.Text.ASCIIEncoding.ASCII
                        .GetString(Convert.FromBase64String(req.Headers["Authorization"].Substring(6)))
                        .Split(':');
            var user = new { Name = credentials[0], Password = credentials[1] };
            if(!(user.Name == "username" && user.Password == "passwords"))
            {
                filterContext.Result = new HttpNotFoundResult();
            }
        }
    }
}

1) Является ли ActionFilterAttribute лучшим способом сделать это?

2) Является ли настройка filterContext.Result правильным способом отказатьдоступ к методу контроллера?

3) Что-то я делаю не так?

Спасибо.

-Ник

Ответы [ 4 ]

12 голосов
/ 24 февраля 2012

1) Является ли ActionFilterAttribute лучшим способом сделать это?
Я так думаю.Этот подход отражает реализацию встроенного атрибута Authorize.

2) Является ли установка filterContext.Result правильным способом запрета доступа к методу контроллера?
Да.Вот для чего это.(1)

3) Есть ли что-то, что я делаю неправильно?

  • Вы предполагаете, что содержимое заголовка авторизации имеет правильный формат иправильно закодирован.
  • Вы предполагаете, что запрос предназначен для базовой аутентификации, а не какой-либо другой схемы аутентификации.
  • Я бы предпочел использовать HttpUnauthorizedResult() для отправки ошибки http 401 вместо httpОшибка 404 через HttpNotFoundResult().

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

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        try
        {
            if (String.IsNullOrEmpty(filterContext.HttpContext.Request.Headers["Authorization"]))
            {
                filterContext.Result = new HttpUnauthorizedResult();
            }
            else
            {
                if (filterContext.HttpContext.Request.Headers["Authorization"].StartsWith("Basic ", StringComparison.InvariantCultureIgnoreCase))
                {
                    string[] credentials = ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(filterContext.HttpContext.Request.Headers["Authorization"].Substring(6))).Split(':');

                    if (credentials.Length == 2)
                    {
                        if (String.IsNullOrEmpty(credentials[0]))
                        {
                            filterContext.Result = new HttpUnauthorizedResult();
                        }
                        else if (!(credentials[0] == "username" && credentials[1] == "passwords"))
                        {
                            filterContext.Result = new HttpUnauthorizedResult();
                        }
                    }
                    else
                    {
                        filterContext.Result = new HttpUnauthorizedResult();
                    }
                }
                else
                {
                    filterContext.Result = new HttpUnauthorizedResult();
                }
            }

            base.OnActionExecuting(filterContext);
        }
        catch
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }

Примечания

  • Я не включил недопустимые проверки символов для имени пользователя и пароля.
  • Я не мог остановиться на том, как реализовать обработку исключений, поэтому я пошел с простотой.

Рекомендации

(1) http://msdn.microsoft.com/en-us/magazine/gg232768.aspx

8 голосов
/ 22 декабря 2012

Рефакторированная версия Адриана

public class BasicAuthenticationAttribute : ActionFilterAttribute
{
    private static readonly string AuthorizationHeader = "Authorization";
    private static readonly string BasicHeader = "Basic ";
    private static readonly string Username = "username";
    private static readonly string Password = "password";
    private static readonly char[] Separator = ":".ToCharArray();

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        try
        {
            if (!Authenticated(filterContext.HttpContext.Request))
                filterContext.Result = new HttpUnauthorizedResult();

            base.OnActionExecuting(filterContext);
        }
        catch
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }

    private bool Authenticated(HttpRequestBase httpRequestBase)
    {
        bool authenticated = false;

        if (String.IsNullOrEmpty(httpRequestBase.Headers[AuthorizationHeader]) == false &&
            httpRequestBase.Headers[AuthorizationHeader].StartsWith(BasicHeader, StringComparison.InvariantCultureIgnoreCase))
        {
            string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(
                httpRequestBase.Headers[AuthorizationHeader].Substring(BasicHeader.Length))).Split(Separator);

            if (credentials.Length == 2 && credentials[0] == Username && credentials[1] == Password)
            {
                authenticated = true;
            }
        }

        return authenticated;
    }
}
0 голосов
/ 28 декабря 2014

Вот своего рода официальный пример для базовой аутентификации:

http://www.asp.net/web-api/overview/security/authentication-filters

Другая статья, теперь использующая OWIN:

https://lbadri.wordpress.com/2013/07/13/basic-authentication-with-asp-net-web-api-using-owin-middleware/

0 голосов
/ 22 февраля 2012

1) Нет, атрибуты ActionFilter не являются хорошим подходом для аутентификации пользователя. (Так как нам нужно выполнить аутентификацию один раз и установить аутентификацию cookie, HttpContext.User будет оставаться аутентифицированным до истечения срока действия куки)

2) Да, настройка filtercontext.Result является идеальным способом предотвращения доступа, (Но вместо назначения HttpNotFoundResult, используйте RedirectResult для перенаправления на страницу входа)

3) Я действительно не понимаю, почему такая реализация для авторизации. Наилучшим подходом было бы иметь действие, которое получит отправленные данные формы (имя пользователя и пароль).и используйте атрибут Authorize для предотвращения несанкционированного доступа.

Ниже приведен код из примера приложения MVC3 по умолчанию в VS2010.

    [HttpPost]
    public ActionResult LogOn(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                    && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...