Реализация авторизации на полях с использованием GraphQL.NET и ASP.NET Core 2 - PullRequest
0 голосов
/ 02 декабря 2018

У меня есть существующий REST API, разработанный с использованием ASP.NET WEB API 2, в котором авторизация обрабатывается путем сохранения всех подробностей имени контроллера и метода действия в xml-файле.

WebAPIAuthorization.xml:

 <?xml version="1.0" encoding="utf-8" ?>
    <WebApiAuthorizationSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <WebApiControllerAuthorizationSettings>
        <WebApiControllerAuthorizationSetting>
          <ControlerName>Profile</ControlerName>
          <IsAuthorizationRequired>true</IsAuthorizationRequired>
          <WebApiActionAuthorizationSettings>
          <WebApiActionAuthorizationSetting>
            <ActionName>GetProfile</ActionName>
            <IsAuthorizationRequired>true</IsAuthorizationRequired>
          </WebApiActionAuthorizationSetting>
          </WebApiActionAuthorizationSettings>
        </WebApiControllerAuthorizationSetting>    
      </WebApiControllerAuthorizationSettings>
    </WebApiAuthorizationSettings>

Код:

public class CommonResponserHandler : DelegatingHandler
{
    ICommonService _commonService = new CommonService();
    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        string locale = string.Empty;
        if (request.Headers.Contains(Constants.REQUEST_HEADER_ACEPT_LANGUAGE))
        {
            locale = request.Headers.GetValues(Constants.REQUEST_HEADER_ACEPT_LANGUAGE).First();
        }

        bool initialAuthorizationStatus = GetInitialAuthorization(request);
        var response = await base.SendAsync(request, cancellationToken);
        APIResult commonResponse;
        if (response.TryGetContentValue<APIResult>(out commonResponse))
        {
            //populate common response here;
            UpdateCommonResponse(request, response, commonResponse);
            HttpResponseMessage newResponse;
            bool authorizatinCheckResult = AssertAuthorization(initialAuthorizationStatus, request);
            if (authorizatinCheckResult)
            {
                newResponse = request.CreateResponse(response.StatusCode, commonResponse);
            }
            else
            {
                var unAuthorisedResult = new APIResult{Authorized = false, UserMessage = Constants.Unauthorized, Locale = new Locale(_commonService.GetLanguageFromLocale(locale))};
                newResponse = request.CreateResponse(HttpStatusCode.Unauthorized, unAuthorisedResult);
                var jsonSerializerSettings = new JsonSerializerSettings{ContractResolver = new CamelCasePropertyNamesContractResolver()};
                HttpContext.Current.Items["401message"] = JsonConvert.SerializeObject(unAuthorisedResult, Formatting.Indented, jsonSerializerSettings);
            }

            //Add headers from old response to new response
            foreach (var header in response.Headers)
            {
                newResponse.Headers.Add(header.Key, header.Value);
            }

            return newResponse;
        }

        return response;
    }

    private bool GetInitialAuthorization(HttpRequestMessage request)
    {
        bool isAuthenticated = false;
        try
        {
            string cookieId = string.Empty;
            IEnumerable<CookieHeaderValue> cookies = request.Headers.GetCookies(Constants.COOKIE_BROWSER_NAME);
            if (cookies.Any())
            {
                IEnumerable<CookieState> cookie = cookies.First().Cookies;
                if (cookie.Any())
                {
                    var cookieValue = cookie.FirstOrDefault(x => x.Name == Constants.COOKIE_BROWSER_NAME);
                    if (cookieValue != null)
                        cookieId = cookieValue.Value.ToLower();
                }
            }

            isAuthenticated = _commonService.IsAuthorized(cookieId);
        }
        catch (Exception ex)
        {
            //log error
            LogUtility.BuildExceptionMessage(ex);
        }

        return isAuthenticated;
    }

    private bool AssertAuthorization(bool initialAuthorizationStatus, HttpRequestMessage request)
    {
        bool authorizationCheckStatus = true;
        //get controller name and action name.
        var data = ((request.GetRouteData().Route.DataTokens as System.Web.Http.Routing.HttpRouteValueDictionary));
        string actionName = ((System.Web.Http.Controllers.HttpActionDescriptor[])data["actions"])[0].ActionName;
        string controllerName = ((System.Web.Http.Controllers.HttpActionDescriptor[])data["actions"])[0].ControllerDescriptor.ControllerName;
        List<WebApiControllerAuthorizationSetting> webApiControllerAuthorizationSettings = WebApiAuthorizationSettings.GetWebApiAuthorizationSettings();
        var controllerAuthorizationSetting = GetControllerSetting(webApiControllerAuthorizationSettings, controllerName);
        if (controllerAuthorizationSetting != null)
        {
            bool isAuthenticationRequired = controllerAuthorizationSetting.IsAuthorizationRequired;
            //if action level settings are available, then the controller settings will be overridden by action level settings
            var actionAuthorizationSetting = GetActionSetting(controllerAuthorizationSetting, actionName);
            if (actionAuthorizationSetting != null)
            {
                //check if the action is anonymous. if so, set the roles to anonymous.
                isAuthenticationRequired = actionAuthorizationSetting.IsAuthorizationRequired;
            }

            if (isAuthenticationRequired)
            {
                if (!initialAuthorizationStatus)
                {
                    authorizationCheckStatus = false;
                }
            }
        }

        return authorizationCheckStatus;
    }
}

Любой запрос на / api / profile должен быть подтвержден для проверки авторизации.В GetInitialAuthorization () первоначальная авторизация выполняется на основе файла cookie, присутствующего в запросе, и оттуда выполняется еще одна проверка по методу: AssertAuthorization (initialAuthorizationStatus, request), где выполняется проверка файла WebAPIAuthorization.xml для обнаружения присутствия.контроллера и метода действия.

Для всех остальных конечных точек API REST авторизация отсутствует.

Я хочу реализовать это для полей GraphQL в тех же строках.

Может кто-нибудьпомогите с некоторыми рекомендациями по реализации этой политики авторизации.

...