401 के बजाय अनधिकृत वेबपीआई कॉल रिटर्निंग लॉगिन पेज


180

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

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

नीचे दो तरीके

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

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

जवाबों:


78

दो ऑथराइज़र वितरित कार्यान्वयन हैं और आपको यह सुनिश्चित करने की आवश्यकता है कि आप वेब एपीआई के लिए सही एक का संदर्भ दे रहे हैं। वहाँ System.Web.Http.AuthorizeAttribute है जो वेब APIs , और System.Web.Mvc.AuthorizeAttribute के लिए उपयोग किया जाता है जो विचारों के साथ नियंत्रकों के लिए उपयोग किया जाता है। यदि प्राधिकरण विफल हो जाता है और Mvc.AuthorizeAttribute लॉगिन पृष्ठ पर अनुप्रेषित करेगा, तो Http.AuthorizeAttribute एक 401 त्रुटि लौटाएगा

अपडेट किया गया 11/26/2013

ऐसा प्रतीत होता है कि चीजें MVC 5 के साथ काफी बदल गई हैं क्योंकि ब्रॉक एलेन ने अपने लेख में बताया है । मुझे लगता है कि ओविन पाइप लाइन ने कुछ नया व्यवहार किया है। अब जब उपयोगकर्ता को अधिकृत नहीं किया जाता है तो 200 की स्थिति HTTP हेडर में निम्नलिखित जानकारी के साथ वापस आ जाती है।

X-Responded-JSON: {"status":401,"headers":{"location":"http:\/\/localhost:59540\/Account\/Login?ReturnUrl=%2Fapi%2FTestBasic"}}

आप त्रुटि शाखा पर 401 स्थिति की तलाश करने के बजाय, इसे कैसे प्रबंधित करें, यह निर्धारित करने के लिए शीर्ष लेख में इस जानकारी की जांच करने के लिए ग्राहक पक्ष पर अपना तर्क बदल सकते हैं।

मैंने OnAuthorization और HandleUnauthorizedRequest विधियों में प्रतिक्रिया में स्थिति सेट करके एक कस्टम प्राधिकारी Attribute में इस व्यवहार को ओवरराइड करने का प्रयास किया ।

actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);

लेकिन यह काम नहीं किया। नई पाइपलाइन को बाद में इस प्रतिक्रिया को पकड़ना चाहिए और इसे उसी प्रतिक्रिया में संशोधित करना चाहिए जो मुझे पहले मिल रही थी। HttpException को फेंकना या तो काम नहीं करता था क्योंकि यह सिर्फ 500 त्रुटि स्थिति में बदल जाता है।

मैंने ब्रॉक एलेन के समाधान का परीक्षण किया और यह तब काम किया जब मैं jQuery के अजाक्स कॉल का उपयोग कर रहा था। यदि यह आपके लिए काम नहीं कर रहा है तो मेरा अनुमान है कि यह इसलिए है क्योंकि आप कोणीय का उपयोग कर रहे हैं। अपना परीक्षण फ़िडलर के साथ चलाएं और देखें कि क्या आपके शीर्षलेख में निम्नलिखित है।

X-Requested-With: XMLHttpRequest

अगर ऐसा नहीं है तो यही समस्या है। मैं कोणीय से परिचित नहीं हूँ लेकिन अगर यह आपको अपने स्वयं के हेडर मान डालने देता है तो इसे अपने ajax अनुरोधों में जोड़ें और यह संभवतः काम करना शुरू कर देगा।


मुझे लगता है कि System.web.http.authorizeattribute का उपयोग करके im, कम से कम इस webapicontroller does not के लिए system.web.mvc का उपयोग कर रहा है, और प्राधिकारी विशेषता की परिभाषा के लिए मुझे system.web.http पर भेजता है
टिम

हाय @ केविन-जंघन अच्छी तरह से यहाँ उलझन में हैं। shiva से ऊपर का उदाहरण एक mvc ऑथराइजेशन विशेषता का उपयोग करता है, जो निश्चित रूप से मुझे webapi एक्शन पर लागू नहीं होना चाहिए। ब्रॉक एलन से उदाहरण या तो काम नहीं करता है या तो यह सोचता है कि जब मैं इसके माध्यम से कदम उठाऊंगा।
टिम

1
केवल इस उत्तर को देखा (थिंकओवरफ़्लो नोटिफ़िकेशन नहीं भेजते हुए सोचें) मैंने समस्या को स्पष्ट करने के लिए एक जीथब्यू उदाहरण जोड़ा है, और अब कोणीय हेडर में अपना फिक्स जोड़ा है। धन्यवाद। हालांकि यह सही नहीं लगता कि प्राधिकृत विशेषता में कोई संपत्ति नहीं है जिसे मैं जांच सकता हूं या आपके द्वारा उल्लिखित मूल कार्यक्षमता काम नहीं कर सकती है।
टिम

3
POSTMAN और हेडर परम एक्स-रिक्वेस्ट-विद का उपयोग करना: XMLHttpRequest मेरे लिए काम करता है ... धन्यवाद
chemitaxis

तो, क्या होगा यदि आपके पास ऐसा करने का इरादा है जो एक शुद्ध वेब एपीआई परियोजना है? मैं एक ऐसी परियोजना पर काम कर रहा हूँ जिसे कोई और स्थापित करता है और प्राधिकरण यहाँ वर्णित के रूप में पुनर्निर्देशित कर रहा है, लेकिन मेरे पास एक अलग एपीआई परियोजना है जो ठीक काम करती है। वहाँ होना चाहिए कुछ लगता है कि यह एक एपीआई अनुप्रयोग के बजाय एक एमवीसी ऐप है, लेकिन मुझे नहीं पता कि यह क्या हो सकता है।
डेरेक ग्रीर

123

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

इसे Startup.Auth.cs फ़ाइल में कॉन्फ़िगर कॉन्फ़िगर विधि में रखें:

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"));
}

68
इस पर एक भिन्नता: यदि आपके सभी वेब एपीआई कॉल एक निश्चित पथ से गुजरते हैं, उदाहरण के लिए /api, आप यह निर्धारित करने के लिए पथ का उपयोग कर सकते हैं कि क्या अनुप्रेषित करना है। यदि आपके पास ऐसे ग्राहक हैं जो JSON जैसे अन्य प्रारूपों का उपयोग करते हैं तो यह विशेष रूप से उपयोगी है। कॉल को इसके IsAjaxRequestसाथ बदलें if (!context.Request.Path.StartsWithSegments(new PathString("/api")))
एडवर्ड ब्रे

पार्टी के लिए देर से, लेकिन यह तरीका मेरे लिए एकमात्र काम है, और अधिक "सटीक" प्रतीत होता है।
स्टीफन कॉलिन्स

पार्टी के लिए देर से (आर), लेकिन यह बहुत उपयोगी साबित हुआ है ... यह मेरे दिमाग को चकरा देता है कि डिफ़ॉल्ट उत्पन्न कोड ऐसा गलत करता है, इस तरह से निराशा में मुश्किल तरीके से डिबग करता है।
निक

यदि आप एक WebApi समाधान के बाद हैं, तो माणिक का जवाब यहां की उच्च मतदान टिप्पणी का एक अच्छा विकल्प है।
डनक

5
C # 6 का उपयोग करते हुए, यहां IsAjaxRequest का एक छोटा संस्करण है: private static bool IsAjaxRequest(IOwinRequest request) { return request.Query?["X-Requested-With"] == "XMLHttpRequest" || request.Headers?["X-Requested-With"] == "XMLHttpRequest"; }
पीटर nerneholm

85

यदि आप asp.net MVC वेब साइट के अंदर asp.net WebApi जोड़ रहे हैं, तो आप संभवतः कुछ अनुरोधों पर अनधिकृत प्रतिक्रिया देना चाहते हैं। लेकिन तब ASP.NET इन्फ्रास्ट्रक्चर चलन में आता है और जब आप HttpStatusCode.Unauthorized पर प्रतिक्रिया स्थिति कोड सेट करने का प्रयास करते हैं, तो आपको लॉगिन पृष्ठ पर 302 रीडायरेक्ट मिलेगा।

यदि आप यहां asp.net आइडेंटिफिकेशन और ओवेन बेस्ड ऑथेंटिकेशन का उपयोग कर रहे हैं तो एक कोड जो उस इश्यू को हल करने में मदद कर सकता है:

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

    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
}


private static bool IsApiRequest(IOwinRequest request)
{
    string apiPath = VirtualPathUtility.ToAbsolute("~/api/");
    return request.Uri.LocalPath.StartsWith(apiPath);
}

1
यदि मैं अनुरोधों को पाठ / html या एप्लिकेशन / xhtml को प्रतिक्रिया के रूप में स्वीकार करता हूं, तो मैंने यह
जांचने के लिए विवेचक

4
मैं इस दृष्टिकोण को भी पसंद करता हूं। मेरे द्वारा बनाया गया एकमात्र जोड़ था लोकलपैथ .TLower () के मामले में वे "/ एपीआई" या कुछ और करने का अनुरोध करते थे।
फर्स्ट डिविज़न

1
बहुत बहुत धन्यवाद। इसने मेरा दिन बचाया। :)
अमित कुमार

क्या किसी को इसके साथ किस्मत है? CookieAuthenticationOptions के पास अब Aspnet Core 1.1 के रूप में प्रदाता की संपत्ति नहीं है।
जेरेमी

27

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

मैंने एक और दृष्टिकोण चुना है कि नए हेडर प्रतिक्रिया को इंजेक्ट करें: 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);
    }
}

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

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

तो, OWIN स्टार्टअप पर आप यह जांचने में सक्षम हैं कि प्रतिक्रिया हैडर क्या है 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;
}

धन्यवाद ! हमारे एपीआई ने Xamarin / Android को छोड़कर हर प्लेटफॉर्म पर काम किया। इस समाधान का उपयोग करेंगे
Jurion

17

ASP.NET के पिछले संस्करणों में, आपको यह काम करने के लिए सामान का एक पूरा गुच्छा करना था ।

अच्छी खबर यह है, क्योंकि आप ASP.NET 4.5 का उपयोग कर रहे हैं। आप नए HttpResponse.SuppressFormsAuthenticationRedirect संपत्ति का उपयोग करके रूपों को पुनर्निर्देशित कर सकते हैं।

इन Global.asax:

protected void Application_EndRequest(Object sender, EventArgs e)
{
        HttpApplication context = (HttpApplication)sender;
        context.Response.SuppressFormsAuthenticationRedirect = true;
}

EDIT : आप सर्गेई ज़्वेज़दीन के इस लेख पर एक नज़र डालना चाहते हैं, जिसमें आपके द्वारा किए जाने वाले काम को पूरा करने का एक अधिक परिष्कृत तरीका है।

प्रासंगिक कोड स्निपेट और लेखक कथन नीचे चिपकाए गए। कोड और कथन के मूल लेखक - सर्गेई ज़्वेज़िन

पहला - आइए यह निर्धारित करें कि क्या वर्तमान HTTP- अनुरोध AJAX- अनुरोध है। यदि हाँ, तो हमें HTTP 302 के साथ HTTP 401 की जगह अक्षम करना चाहिए:

public class ApplicationAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        var httpContext = filterContext.HttpContext;
        var request = httpContext.Request;
        var response = httpContext.Response;

        if (request.IsAjaxRequest())
            response.SuppressFormsAuthenticationRedirect = true;

        base.HandleUnauthorizedRequest(filterContext);
    }
}

दूसरा - चलो एक शर्त जोड़ते हैं :: यदि उपयोगकर्ता प्रमाणित होता है, तो हम HTTP 403 भेजेंगे; और HTTP 401 अन्यथा।

public class ApplicationAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        var httpContext = filterContext.HttpContext;
        var request = httpContext.Request;
        var response = httpContext.Response;
        var user = httpContext.User;

        if (request.IsAjaxRequest())
        {
            if (user.Identity.IsAuthenticated == false)
                response.StatusCode = (int)HttpStatusCode.Unauthorized;
            else
                response.StatusCode = (int)HttpStatusCode.Forbidden;

            response.SuppressFormsAuthenticationRedirect = true;
            response.End();
        }

        base.HandleUnauthorizedRequest(filterContext);
    }
}

बहुत बढ़िया। अब हमें इस नए फिल्टर के साथ सभी प्राधिकरणों को मानक प्राधिकृत करने की जगह लेनी चाहिए। यह उन अपराधियों के लिए लागू नहीं हो सकता है, जो कोड के एस्टे हैं। लेकिन मुझे कोई रास्ता नहीं पता है। यदि आपके पास है, तो कृपया टिप्पणियों पर जाएं।

अंतिम, जो हमें करना चाहिए - क्लाइंट-साइड पर HTTP 401/403 हैंडलिंग को जोड़ने के लिए। हम कोड दोहराव से बचने के लिए jQuery में ajaxError का उपयोग कर सकते हैं:

$(document).ajaxError(function (e, xhr) {
    if (xhr.status == 401)
        window.location = "/Account/Login";
    else if (xhr.status == 403)
        alert("You have no enough permissions to request this resource.");
});

परिणाम -

  • यदि उपयोगकर्ता को प्रमाणित नहीं किया गया है, तो वह किसी भी AJAX-कॉल के बाद एक लॉगिन पृष्ठ पर पुनः निर्देशित किया जाएगा।
  • यदि उपयोगकर्ता को प्रमाणित किया गया है, लेकिन उसके पास पर्याप्त अनुमति नहीं है, तो वह उपयोगकर्ता के अनुकूल एरोर संदेश देखेगा।
  • यदि उपयोगकर्ता प्रमाणित है और उसके पास पर्याप्त अनुमति है, तो कोई त्रुटि नहीं है और HTTP-अनुरोध हमेशा की तरह आगे बढ़ेगा।

Im मैं पीवीसी के माध्यम से नए पहचान फ्रेमवर्क का उपयोग कर रहा हूँ। क्या यह सेटिंग mvc लॉगिन को वेबपी कॉल के साथ-साथ काम करने से नहीं रोक पाएगी?
टिम

5
जब मैंने इस उदाहरण की जाँच की तो यह प्रकट होता है कि अधिकृत विशेषता का उपयोग किया जा रहा है जो कि WebApi संस्करण के बजाय MVC संस्करण है। हालांकि webapi संस्करण में प्रामाणिकता के रूपों को दबाने के लिए विकल्प नहीं हैं।
टिम

मेरे अनुरोध में एक IsAjaxRequest विधि नहीं है।
टिम

1
टिम इस IsAjaxRequest के लिए इसे देखें: brockallen.com/2013/10/27/… यदि आप हेडर को संपादित किए बिना AngularJs का उपयोग कर रहे हैं, तो आपके पास "XMLHttpRequest" नहीं होगा और या तो इसे जोड़ें या कुछ और जांचें।
टिम

10

यदि आप Web APIअपनी MVCपरियोजना के भीतर से भाग रहे हैं , तो आपको AuthorizeAttributeअपने APIतरीकों पर लागू करने के लिए एक कस्टम बनाने की आवश्यकता होगी । भीतर IsAuthorized overrideआप वर्तमान हड़पने के लिए की जरूरत है HttpContextक्रम में इस तरह पुनर्निर्देशन रोकने के लिए,:

    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        if (string.IsNullOrWhiteSpace(Thread.CurrentPrincipal.Identity.Name))
        {
            var response = HttpContext.Current.Response;
            response.SuppressFormsAuthenticationRedirect = true;
            response.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
            response.End();
        }

        return base.IsAuthorized(actionContext);
    }

8

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

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

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

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


यह एक संबंधित प्रश्न के लिए प्रस्तावित समाधान के समान है: stackoverflow.com/questions/34997674/…
Guillaume LaHaye

6

मेरे पास WebApi (OWIN का उपयोग करके) के साथ एक MVC5 एप्लिकेशन (System.Web) भी था और सिर्फ WebApi से 401 प्रतिक्रियाओं को 302 प्रतिक्रियाओं में बदलने से रोकना चाहता था।

मेरे लिए इस तरह से WebApi प्राधिकारी के अनुकूलित संस्करण बनाने के लिए काम किया गया था:

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

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


काम करता है, लेकिन अब मेरे पास समस्या है कि क्लाइंट को 401 के बजाय स्थिति -1 प्राप्त होती है
सेबेस्टियन रोजस

@ SebastiánRojas मुझे यकीन नहीं है कि क्या कारण होगा कि - SuppressFormsAuthenticationRedirect झंडा स्थापित करने के कारण यह मेरे लिए मौजूदा 401 को वापस कर सकता है।
जोनो जॉब

3

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

स्थापित करें-पैकेज 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"));
    }
}

ऐसा करने के लिए आवश्यक सभी मैं इस फिल्टर जोड़ सकते हैं और अपने काम कर रहा था config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));अन्यथा User.Identity.IsAuthenticatedहमेशा होता हैfalse
रिकार्डो Saracino

1

यदि आप सामग्री-प्रकार == एप्लिकेशन / जसन को पकड़ना चाहते हैं, तो आप उस कोड का उपयोग कर सकते हैं:

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

        IReadableStringCollection queryJSON = request.Query;
        if ((queryJSON != null) && (queryJSON["Content-Type"] == "application/json"))
        {
            return true;
        }

        IHeaderDictionary headersXML = request.Headers;
        var isAjax = ((headersXML != null) && (headersXML["X-Requested-With"] == "XMLHttpRequest"));

        IHeaderDictionary headers = request.Headers;
        var isJson = ((headers != null) && (headers["Content-Type"] == "application/json"));

        return isAjax || isJson;

    }

सादर!!


1

मुझे मुश्किल समय मिल रहा था कि दोनों स्टेटस कोड और OnAuthorization / HandleUnauthorizedRequest विधियों में काम करने वाली एक पाठ प्रतिक्रिया। यह मेरे लिए सबसे अच्छा समाधान निकला:

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

1

बहुत सारे उपद्रव के बाद लॉगिन पेज पर रीडायरेक्ट से बचने की कोशिश करने के बाद, मुझे एहसास हुआ कि यह वास्तव में अधिकृत विशेषता के लिए काफी उपयुक्त है। यह कह रहा है कि जाओ और प्राधिकरण प्राप्त करो। अपी कॉल्स के लिए जो अधिकृत नहीं हैं, मैं सिर्फ हैकर्स होने के लिए किसी भी जानकारी को प्रकट नहीं करना चाहता था। यह उद्देश्य प्राधिकृत से प्राप्त एक नई विशेषता को जोड़कर सीधे हासिल करना आसान था जो सामग्री को 404 त्रुटि के रूप में छिपाता है:

public class HideFromAnonymousUsersAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
         actionContext.Response = ActionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, "Access Restricted");
    }
}

1

MVC और WebAPI को मिलाकर, यदि अनुरोध अनधिकृत है, तो यह WebAPI अनुरोध में भी लॉगिन पृष्ठ पर रीडायरेक्ट करेगा। उसके लिए, हम मोबाइल एप्लिकेशन पर प्रतिक्रिया भेजने के लिए नीचे कोड जोड़ सकते हैं

protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
{
    var httpContext = HttpContext.Current;
    if (httpContext == null)
    {
        base.HandleUnauthorizedRequest(actionContext);
        return;
    }

    actionContext.Response = httpContext.User.Identity.IsAuthenticated == false ?
        actionContext.Request.CreateErrorResponse(
      System.Net.HttpStatusCode.Unauthorized, "Unauthorized") :
       actionContext.Request.CreateErrorResponse(
      System.Net.HttpStatusCode.Forbidden, "Forbidden");

    httpContext.Response.SuppressFormsAuthenticationRedirect = true;
    httpContext.Response.End();
}

0

धन्यवाद दोस्तों!

मेरे मामले में, मैंने क्यूंग्ले और शिव के उत्तरों को संयुक्त किया , और कुछ इस तरह से मिला:

API अपवादों के लिए नियंत्रक के अपवाद () हैंडलर में:

filterContext.ExceptionHandled = true;
//...
var response = filterContext.HttpContext.Response;
response.Headers.Add("Suppress-Redirect", "true");
response.SuppressFormsAuthenticationRedirect = true;

ऐप स्टार्टअप कॉन्फिगर कोड में:

app.UseCookieAuthentication(new CookieAuthenticationOptions {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        Provider = new CookieAuthenticationProvider {
            OnValidateIdentity = ctx => {
                return validateFn.Invoke(ctx);
            },
            OnApplyRedirect = ctx =>
            {
                bool enableRedir = true;
                if (ctx.Response != null)
                {
                    string respType = ctx.Response.ContentType;
                    string suppress = ctx.Response.Headers["Suppress-Redirect"];
                    if (respType != null)
                    {
                        Regex rx = new Regex("^application\\/json(;(.*))?$",
                            RegexOptions.IgnoreCase);
                        if (rx.IsMatch(respType))
                        {
                            enableRedir = false;
                        }  
                    }
                    if ((!String.IsNullOrEmpty(suppress)) && (Boolean.Parse(suppress)))
                    {
                        enableRedir = false;
                    }
                }
                if (enableRedir)
                {
                    ctx.Response.Redirect(ctx.RedirectUri);
                }
            }
        }
    });

-1

MVC 5 में डॉट नेट फ्रेमवर्क 4.5.2 के साथ हमें "स्वीकार / शीर्षक" के तहत "एप्लिकेशन / जसन, वादी पाठ .." मिल रहा है। निम्नलिखित की तरह उपयोग करना अच्छा होगा:

isJson = headers["Content-Type"] == "application/json" || headers["Accept"].IndexOf("application/json", System.StringComparison.CurrentCultureIgnoreCase) >= 0;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.