Mvc Api получить учетные данные из запроса - PullRequest
0 голосов
/ 16 мая 2018

У меня есть куча времени, чтобы найти что-нибудь об этом, хотя я думаю, что это довольно просто ...

Я занимаюсь разработкой API с использованием .NET MVC 4.5.Я хочу, чтобы конечный пользователь мог отправить запрос, например (PowerShell):

$webclient = new-object System.Net.WebClient
$webclient.Credentials = new-object System.Net.NetworkCredential($username, 
$securePassword)
$doc = $webclient.DownloadString("http://localhost:60023/api/getData?id=200")

Но я не знаю, как получить учетные данные из запроса в моем приложении.

Мой контроллер выглядит так:

namespace App.Controllers
{
    public IEnumerable<MyStruct> Get(int id)
    {
        // TODO: get credentials from request

        // validate credentials
        // code to create IEnumerable<MyStruct>
        return DataList;
    }
}

Пока все работает, если я жестко закодирую учетные данные, все, что мне нужно выяснить, это как получить учетные данные от конечного пользователя $webclient.Credentials.

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

Я ухожу?

Разве это не хороший способ аутентификации запросов API?Я знаю, что есть атрибут [Authorize], который может использовать встроенную систему аутентификации, но мое приложение использует пользовательскую проверку входа в систему, поэтому я не думаю, что это будет работать.Есть ли причина, по которой проверка учетных данных в методе Controller способом, который я хочу, является плохой идеей?

1 Ответ

0 голосов
/ 16 мая 2018

Обычно MVC не используется для работы API.В то время как MVC может обрабатывать вызовы API, Microsoft имеет MVC подобный продукт под названием WebApi, который более приспособлен для обслуживания API, например, возвращает JSON или XML вместо представления.

В обоих случаяхMVC и WebApi, обработка аутентификации и авторизации внутри методов не рекомендуется.Пока он работает, он открывает вам возможность забыть о защите вызова API.Поэтому Microsoft создала атрибуты AuthenticationFilter и AuthorizationFilter.Они позволяют вам отмечать, какие API или представления должны быть защищены методом, классом или приложением.

Чтобы получить доступ к основным учетным данным из запроса в MVC, вам потребуется доступ к заголовку авторизации.Это будет строка в виде Basic [Base64Encoded, colon delimited strings].

В следующем коде показан грубый пример того, как считывать учетные данные:

public ActionResult TestView()
{
    bool isAuthenticated;
    var base64Header = Request.Headers["Authorization"];
    //The header is a string in the form of "Basic [base64 encoded username:password]"
    if (base64Header != null)
    {
        var authHeader = AuthenticationHeaderValue.Parse(base64Header);
        if (authHeader != null
            && authHeader.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase)
            && authHeader.Parameter != null)
        {
            //Decode the username:password pair
            var credentialPair = Encoding.ASCII.GetString(Convert.FromBase64string(authHeader.Parameter));

            //Split into pieces
            var credentials = credentialPair.Split(new [] {":"}, StringSplitOptions.None);
            var userName = credentials[0];
            var plainTextPassword = credentials[1];
            isAuthenticated = SomeAuthenticator.Authenticate(userName, password);
        }
    }
    if (isAuthenticated)
       return Foo();
    else
       RedirectResult("your login view");
}

Было бы лучше вставить этот кодв AuthenticationFilter однако.Это дает вам возможность включать / выключать авторизацию по методу, классу или приложению.

public class CustomAuthFilter : IAuthenticationFilter
{
    public void OnAuthentication(AuthenticationContext filterContext)
    {
        var header = filterContext.RequestContext.HttpContext.Request.Headers["Authorization"];
        if (!Authenticate(header))
            filterContext.Result = new HttpUnauthorizedResult();
    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
       filterContext.Result = new RedirectResult(@"https:\\foo\YourLoginPage");
    }

    private bool Authenticate(string rawAuthorizationHeader)
    {
        try
        {
            if (rawAuthorizationHeader != null)
            {
                var authHeader = AuthenticationHeaderValue.Parse(rawAuthorizationHeader);
                if (authHeader != null
                    && authHeader.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase)
                    && authHeader.Parameter != null)
                {
                    var credentialPair = Encoding.ASCII.GetString(Convert.FromBase64String(authHeader.Parameter));
                    var credentials = credentialPair.Split(new[] { ":" }, StringSplitOptions.None);
                    var userName = credentials[0];
                    var plainTextPassword = credentials[1];
                    return SomeAuthenticator.Authenticate(userName, plainTextPassword);
                }
            }

            return false;
        }
        catch (Exception)
        {
            return false;
        }
    }
}

И затем использовать

[CustomAuthFilter] //Secure all methods in the class
public class SecureApiController
{

    public ActionResult SecuredApiCall()
    {
        return Foo();
    }

    public ActionResult AnotherSecuredCall()
    {
        return Bar();
    }

    [AllowAnonymous]
    public ActionResult UnsecuredApiCall()
    {
        return UnsecureFoo();
    }
}

Обратите внимание, что в типичном для Microsoft стиле, Аутентификация и Авторизация - это две разные вещи.Вам нужно будет установить фильтр авторизации, если вы хотите защитить API более чем «у этого пользователя есть учетная запись».

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