Делаем авторизацию на основе базовой http аутентификации

В прошлой заметке я описывал как работать с базовой аутентификацией. Минус в этом подходе в том что логин и пароль браузер будет отсылать каждый раз, когда будет запрашиваться страница с ограниченным доступом. Но можно исправит этот недочет. Отослать логин и пароль один раз, а затем на сервере записать в сессию текущего пользователя, то есть все как и с обычной авторизацией.

public class HttpAuthController : Controller
{

    private void LoginPrompt(bool sendBody = true)
    {
        Response.AppendHeader("WWW-Authenticate", "Basic realm=\"My Realm\"");
        Response.StatusCode = 401;
        if (sendBody)
            Response.Write("Вы отменили авторизацию, <a href='" + GetBaseUrl() + "HttpAuth'>перейти на главную страницу</a>");
        Response.End();
    }

    private string GetBaseUrl()
    {
        return HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority +
HttpContext.Request.ApplicationPath.TrimEnd('/') + "/";
    }
    public string Index()
    {
        bool isAuthenticated = Session["IsAuthenticated"] != null ? (bool)Session["IsAuthenticated"] : false;
        string content = "";
        if (isAuthenticated)
        {
            string userName = (string)Session["UserName"];
            content += @"Hi " + userName + @"!<br/>
            <a id='logout' href='" + GetBaseUrl().Replace("http://", "http://anonymous:nopasw@") + @"HttpAuth/Logout'>Выйти</a><br/><br/><br/>
            <script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
            <script>
            // фикс для ie
            $('#logout').on('click', function() {
                if (document.all)
                {
                    document.execCommand('ClearAuthenticationCache');
                    window.location = '/';
                }
            });
            // -- -- --
            </script>";
        }
        else
        {
            content += "<a href='" + GetBaseUrl() + "HttpAuth/Login'>Войти</a><br/><br/><br/>";
        }
        content += "Вы не увидите следующий текст, если вы не авторизованы: "
            + (isAuthenticated ? "Ридиска - нехороший человек!" : "");
        return content;
    }
    public ActionResult Login()
    {
        if (String.IsNullOrEmpty(Request.Headers["Authorization"]))
        {
            LoginPrompt();
            return null;
        }
        // проверяем логин и пароль
        var cred = System.Text.UTF8Encoding.UTF8
        .GetString(Convert.FromBase64String(Request.Headers["Authorization"].Substring(6)))
        .Split(':');
        string userName = cred[0];
        string password = cred[1];
        // собственно здесь должна быть сама проверка
        if (!userName.Equals("Admin") || !password.Equals("123456"))
        {
            LoginPrompt();
            return null;
        }
        Session["IsAuthenticated"] = true;
        Session["UserName"] = userName;
        return RedirectToAction("Index", "HttpAuth");
    }
    public ActionResult Logout()
    {
        // фикс для chrome
        bool isAuthenticated = Session["IsAuthenticated"] != null ? (bool)Session["IsAuthenticated"] : false;
        if (isAuthenticated && String.IsNullOrEmpty(Request.Headers["Authorization"]))
        {
            LoginPrompt(false);
            return null;
        }
        // -- -- --
        Session.RemoveAll();

        // фикс для firefox
        return Redirect(GetBaseUrl() + "/HttpAuth");
        // -- -- --
        // return RedirectToAction("Index", "HttpAuth");
    }
}

В данном коде представлены три контроллера — Index, Login и Logout. Первый контроллер отображает ссылку Войти / Выход  (в зависимости от того авторизован пользователь или нет) и текст который доступен только авторизованным пользователям.
Как видно из кода ссылка «Выход» представлена как http://anonymous:nopasw@example.com/HttpAuth/Logout. При клике на такую ссылку браузер делает запрос с заголовком Authorization с логином  anonymous и паролем nopasw. Такого пользователя нет и тем самым делается как бы разлогинивание текущего пользователя. IE не понимает такие ссылки, но зато позволяет очистить кэш авторизации. Хром делает два запроса — сначала без заголовка Authorization, а затем с заголовком. В принципе логично — зачем отсылать лишний раз на сервер логин и пароль, что небезопасно, если сервер их не запрашивал. Firefox выводит сообщение — типа действительно ли пользователь хочет войти на сайт под  пользователем anonymous, если делается локальный редирект.
Вот и все, авторизация готова! Не пришлось писать html форму, затем отсылать ее на сервер.
PS: на самом деле выигрыша получилось мало — что передавать пароль, что передавать куки — все равно небезопасно. Лучше использовать https.

Делаем авторизацию на основе базовой http аутентификации: Один комментарий

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>