[C#] अनधिकृत वेबपी कॉल 401 के बजाय लॉगिन पेज लौटा रहा है


Answers

कुकी प्रमाणीकरण और ओविन का उपयोग करते समय एजेक्स कॉल के लिए 401 को वापस करने के तरीके पर ब्रॉक एलन का एक अच्छा ब्लॉग पोस्ट है। http://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/

इसे Startup.Auth.cs फ़ाइल में ConfigureAuth विधि में रखें:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
  AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
  LoginPath = new PathString("/Account/Login"),
  Provider = new CookieAuthenticationProvider
  {
    OnApplyRedirect = ctx =>
    {
      if (!IsAjaxRequest(ctx.Request))
      {
        ctx.Response.Redirect(ctx.RedirectUri);
      }
    }
  }
});

private static bool IsAjaxRequest(IOwinRequest request)
{
  IReadableStringCollection query = request.Query;
  if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest"))
  {
     return true;
  }
  IHeaderDictionary headers = request.Headers;
  return ((headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest"));
}
Question

मैं अपने एमवीसी / वेबपीआई प्रोजेक्ट को कैसे कॉन्फ़िगर कर सकता हूं ताकि एक रेजर व्यू से बुलाया गया वेबपैआई विधि अनधिकृत होने पर लॉगिन पेज वापस न करे?

इसका एक एमवीसी 5 एप्लीकेशन है जिसमें जावास्क्रिप्ट के माध्यम से कॉल के लिए वेबएपीआई नियंत्रक भी हैं।

नीचे दो विधियां

[Route("api/home/LatestProblems")]      
[HttpGet()]
public List<vmLatestProblems> LatestProblems()
{
    // Something here
}

[Route("api/home/myLatestProblems")]
[HttpGet()]
[Authorize(Roles = "Member")]
public List<vmLatestProblems> mylatestproblems()
{
   // Something there
}

निम्नलिखित कोणीय कोड के माध्यम से बुलाया जाता है:

angular.module('appWorship').controller('latest', 
    ['$scope', '$http', function ($scope,$http) {         
        var urlBase = baseurl + '/api/home/LatestProblems';
        $http.get(urlBase).success(function (data) {
            $scope.data = data;
        }).error(function (data) {
            console.log(data);
        });
        $http.get(baseurl + '/api/home/mylatestproblems')
          .success(function (data) {
            $scope.data2 = data;
        }).error(function (data) {
            console.log(data);
        });  
    }]
);

इसलिए मैं लॉग इन नहीं हूं और पहली विधि सफलतापूर्वक डेटा लौटाती है। दूसरी विधि रिटर्न (सफलता समारोह में) डेटा जिसमें लॉगिन पृष्ठ के बराबर होता है। यानी एमवीसी में आपको क्या मिलेगा यदि आपने नियंत्रक कार्रवाई का अनुरोध किया था जो [अधिकृत] के साथ मुद्रित था और आप लॉग इन नहीं थे।

मैं चाहता हूं कि यह 401 अनधिकृत लौटाए, ताकि मैं उपयोगकर्ताओं के लिए अलग-अलग डेटा प्रदर्शित कर सकूं, अगर वे लॉग इन हैं या नहीं। आदर्श रूप में यदि उपयोगकर्ता लॉग इन है तो मैं नियंत्रक की उपयोगकर्ता संपत्ति तक पहुंचने में सक्षम होना चाहता हूं, इसलिए मैं उस सदस्य को विशिष्ट डेटा वापस कर सकता हूं।

अद्यतन: चूंकि नीचे दिए गए कोई भी सुझाव अब काम नहीं कर रहे हैं (पहचान या वेबएपीआई में परिवर्तन) आईव ने जिथब पर एक कच्चा उदाहरण बनाया है जो समस्या को स्पष्ट करना चाहिए।




मुझे वही स्थिति मिली जब ओविन हमेशा WebApi से लॉगिन पेज पर 401 प्रतिक्रिया को रीडायरेक्ट करता है। हमारा वेब एपीआई न केवल कोणीय से एजेक्स कॉल का समर्थन करता है बल्कि मोबाइल, विन फॉर्म कॉल भी करता है। इसलिए, यह जांचने का समाधान है कि अनुरोध AJAX अनुरोध है या नहीं, वास्तव में हमारे मामले के लिए हल नहीं किया गया है।

मैंने नया हेडर प्रतिक्रिया इंजेक्ट करने के लिए एक और तरीका चुना है: अगर प्रतिक्रियाएं वेबएपी से आती हैं तो दबाएं Suppress-Redirect । कार्यान्वयन हैंडलर पर है:

public class SuppressRedirectHandler : DelegatingHandler
{
    /// <summary>
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        return base.SendAsync(request, cancellationToken).ContinueWith(task =>
        {
            var response = task.Result;
            response.Headers.Add("Suppress-Redirect", "True");
            return response;
        }, cancellationToken);
    }
}

और इस हैंडलर को वेबएपी के वैश्विक स्तर पर पंजीकृत करें:

config.MessageHandlers.Add(new SuppressRedirectHandler());

तो, ओविन स्टार्टअप पर आप यह जांचने में सक्षम हैं कि प्रतिक्रिया हेडर में Suppress-Redirect :

public void Configuration(IAppBuilder app)
{
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationMode = AuthenticationMode.Active,
        AuthenticationType = DefaultApplicationTypes.ApplicationCookie,
        ExpireTimeSpan = TimeSpan.FromMinutes(48),

        LoginPath = new PathString("/NewAccount/LogOn"),

        Provider = new CookieAuthenticationProvider()
        {
            OnApplyRedirect = ctx =>
            {
                var response = ctx.Response;
                if (!IsApiResponse(ctx.Response))
                {
                    response.Redirect(ctx.RedirectUri);
                }
            }
        }
    });
}

private static bool IsApiResponse(IOwinResponse response)
{
    var responseHeader = response.Headers;

    if (responseHeader == null) 
        return false;

    if (!responseHeader.ContainsKey("Suppress-Redirect"))
        return false;

    if (!bool.TryParse(responseHeader["Suppress-Redirect"], out bool suppressRedirect))
        return false;

    return suppressRedirect;
}



Azure Active Directory एकीकरण का उपयोग करके, CookieAuthentication मिडलवेयर का उपयोग करने का दृष्टिकोण मेरे लिए काम नहीं करता था। मुझे निम्नलिखित करना था:

app.UseOpenIdConnectAuthentication(
    new OpenIdConnectAuthenticationOptions
    {
        ...
        Notifications = new OpenIdConnectAuthenticationNotifications
        {   
            ...         
            RedirectToIdentityProvider = async context =>
            {
                if (!context.Request.Accept.Contains("html"))
                {
                    context.HandleResponse();
                }
            },
            ...
        }
    });

यदि अनुरोध ब्राउज़र से आता है (और उदाहरण के लिए, AJAX कॉल नहीं) तो स्वीकार करने वाले शीर्षलेख में स्ट्रिंग html कहीं भी होगा। केवल जब ग्राहक HTML स्वीकार करता है तो मैं कुछ रीडायरेक्ट को कुछ उपयोगी मानता हूं।

मेरा क्लाइंट एप्लिकेशन 401 को उपयोगकर्ता को सूचित कर सकता है कि ऐप के पास और अधिक पहुंच नहीं है और फिर से लॉगिन करने के लिए पुनः लोड करने की आवश्यकता है।




मेरे पास वेबएपीआई (ओडब्ल्यूआईएन का उपयोग करके) के साथ एक एमवीसी 5 एप्लीकेशन (सिस्टमवेब) भी था और बस वेबएपी से 401 प्रतिक्रियाओं को 302 प्रतिक्रियाओं में बदलना चाहता था।

मेरे लिए क्या काम किया गया था WebApi AuthorizeAttribute का एक अनुकूलित संस्करण बनाना:

public class MyAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        base.HandleUnauthorizedRequest(actionContext);
        HttpContext.Current.Response.SuppressFormsAuthenticationRedirect = true;
    }
}

और मानक WebApi AuthorizeAttribute के स्थान पर इसका उपयोग करने के लिए। मैंने एमवीसी व्यवहार को अपरिवर्तित रखने के लिए मानक एमवीसी प्राधिकरण एट्रिब्यूट का उपयोग किया।




मुझे ऑन-प्रमाणीकरण / हैंडल यूनाधिकृत रिक्वेस्ट विधियों में काम कर रहे स्टेटस कोड और टेक्स्ट प्रतिक्रिया दोनों को मुश्किल समय मिल रहा था। यह मेरे लिए सबसे अच्छा समाधान साबित हुआ:

    actionContext.Response = new HttpResponseMessage()
    {
        StatusCode = HttpStatusCode.Forbidden,
        Content = new StringContent(unauthorizedMessage)
    };



बस निम्नलिखित नेगेट पैकेज स्थापित करें

इंस्टॉल-पैकेज Microsoft.AspNet.WebApi.Owin

WebApiConfig फ़ाइल में निम्न कोड लिखें।

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        //Web API configuration and services
        //Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));
    }
}



Links