Panggilan webapi yang tidak sah mengembalikan halaman login daripada 401

180

Bagaimana cara mengkonfigurasi proyek mvc / webapi saya sehingga metode webapi yang dipanggil dari tampilan silet tidak mengembalikan halaman login saat itu tidak sah?

Ini adalah aplikasi MVC5 yang juga memiliki pengontrol WebApi untuk panggilan melalui javascript.

Dua metode di bawah ini

[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
}

dipanggil melalui kode sudut berikut:

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

Jadi saya tidak masuk dan metode pertama berhasil mengembalikan data. metode kedua mengembalikan (dalam fungsi keberhasilan) data yang berisi setara dengan halaman login. yaitu apa yang akan Anda dapatkan di MVC jika Anda meminta tindakan pengontrol yang dicap dengan [Otorisasi] dan Anda tidak masuk.

Saya ingin mengembalikan 401 tanpa izin, sehingga saya dapat menampilkan data yang berbeda untuk pengguna berdasarkan apakah mereka masuk atau tidak. Idealnya jika pengguna login saya ingin dapat mengakses properti Pengguna Pengendali sehingga saya dapat mengembalikan data khusus untuk Anggota itu.

PEMBARUAN: Karena tidak ada saran di bawah ini yang tampaknya berfungsi lagi (perubahan pada Identity atau WebAPI) ive membuat contoh mentah tentang github yang seharusnya menggambarkan masalah tersebut.

Tim
sumber

Jawaban:

78

Ada dua implementasi AuthorizeAttribute dan Anda perlu memastikan bahwa Anda merujuk yang benar untuk API Web. Ada System.Web.Http.AuthorizeAttribute yang digunakan untuk Web API, dan System.Web.Mvc.AuthorizeAttribute yang digunakan untuk pengontrol dengan tampilan. Http.AuthorizeAttribute akan mengembalikan kesalahan 401 jika otorisasi gagal dan Mvc.AuthorizeAttribute akan mengarahkan ulang ke halaman login.

Diperbarui 11/26/2013

Jadi tampaknya banyak hal telah berubah secara drastis dengan MVC 5 seperti yang ditunjukkan Brock Allen dalam artikelnya . Saya kira pipa OWIN mengambil alih dan memperkenalkan beberapa perilaku baru. Sekarang ketika pengguna tidak diotorisasi, status 200 dikembalikan dengan informasi berikut di header HTTP.

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

Anda bisa mengubah logika Anda di sisi klien untuk memeriksa informasi ini di header untuk menentukan cara menangani ini, alih-alih mencari status 401 pada cabang kesalahan.

Saya mencoba untuk menimpa perilaku ini dalam kustom AuthorizeAttribute dengan menetapkan status dalam respons dalam metode OnAuthorization dan HandleUnauthorizedRequest .

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

Tetapi ini tidak berhasil. Pipa baru harus mengambil respons ini nanti dan memodifikasinya menjadi respons yang sama dengan yang saya dapatkan sebelumnya. Melempar HttpException tidak berhasil karena hanya diubah menjadi status kesalahan 500.

Saya menguji solusi Brock Allen dan itu berhasil ketika saya menggunakan panggilan ajax jQuery. Jika tidak bekerja untuk Anda, tebakan saya adalah karena Anda menggunakan sudut. Jalankan tes Anda dengan Fiddler dan lihat apakah yang berikut ada di header Anda.

X-Requested-With: XMLHttpRequest

Jika tidak maka itu masalahnya. Saya tidak terbiasa dengan sudut tetapi jika memungkinkan Anda memasukkan nilai header Anda sendiri kemudian tambahkan ini ke permintaan ajax Anda dan itu mungkin akan mulai bekerja.

Kevin Junghans
sumber
Saya pikir saya menggunakan System.web.http.authorizeattribute, setidaknya webapicontroller ini tidak memiliki penggunaan untuk system.web.mvc, dan pergi ke definisi atribut otorisasi mengirim saya ke system.web.http
Tim
Hai @ kevin-junghans benar-benar bingung di sini. contoh di atas dari shiva menggunakan atribut otorisasi mvc yang tentunya saya tidak boleh menerapkan ke tindakan webapi, Contoh dari Brock allen tampaknya tidak berfungsi baik itu tidak berpikir itu permintaan ajax ketika saya melangkah.
Tim
1
hanya melihat jawaban ini (anggap stackoverflow tidak mengirim pemberitahuan) Saya telah menambahkan contoh github untuk menggambarkan masalah, dan sekarang menambahkan perbaikan Anda ke header sudut. Terima kasih. Namun tampaknya tidak benar bahwa tidak ada properti dalam atribut otorisasi yang dapat saya periksa atau fungsi asli yang Anda sebutkan tidak berfungsi lagi.
Tim
3
Menggunakan POSTMAN dan header param X-Requested-With: XMLHttpRequest berfungsi untuk saya ... terima kasih
chemitaxis
Jadi, bagaimana jika Anda memiliki apa yang Anda inginkan untuk menjadi proyek Web API murni yang melakukan ini? Saya sedang mengerjakan proyek yang diatur oleh orang lain dan Otorisasi mengalihkan seperti dijelaskan di sini, tetapi saya memiliki proyek API lain yang berfungsi dengan baik. Pasti ada sesuatu yang membuat ini berpikir itu adalah aplikasi MVC daripada aplikasi API, tapi saya tidak dapat menemukan apa yang mungkin membuangnya.
Derek Greer
123

Brock Allen memiliki posting blog yang bagus tentang cara mengembalikan 401 untuk panggilan ajax saat menggunakan otentikasi Cookie dan OWIN. http://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/

Masukkan ini dalam metode ConfigureAuth dalam file 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"));
}
Olav Nybø
sumber
68
Variasi untuk ini: Jika semua panggilan API Web Anda melewati jalur tertentu, misalnya /api, Anda dapat menggunakan jalur untuk menentukan apakah akan mengarahkan ulang. Ini sangat berguna jika Anda memiliki klien yang menggunakan format lain seperti JSON. Ganti panggilan IsAjaxRequestdengan if (!context.Request.Path.StartsWithSegments(new PathString("/api"))).
Edward Brey
Terlambat ke pesta, tetapi metode ini adalah satu-satunya yang bekerja untuk saya, dan tampaknya lebih "akurat."
Stephen Collins
Bahkan terlambat (r) ke pesta, tetapi ini telah terbukti sangat berguna ... itu mengejutkan saya bahwa kode yang dihasilkan secara default melakukan hal yang salah, sedemikian sulitnya untuk melakukan debug.
Nick
Jika Anda mencari solusi WebApi, jawaban Manik adalah alternatif yang baik untuk komentar yang sangat dipilih di sini.
Dunc
5
Menggunakan C # 6, berikut adalah versi yang lebih kecil dari IsAjaxRequest: private static bool IsAjaxRequest(IOwinRequest request) { return request.Query?["X-Requested-With"] == "XMLHttpRequest" || request.Headers?["X-Requested-With"] == "XMLHttpRequest"; }
Peter Örneholm
85

Jika Anda menambahkan asp.net WebApi di dalam situs web asp.net MVC, Anda mungkin ingin menanggapi permintaan yang tidak sah. Tapi kemudian infrastruktur ASP.NET ikut bermain dan ketika Anda mencoba untuk mengatur kode status tanggapan ke HttpStatusCode. Tidak Diotorisasi Anda akan mendapatkan 302 redirect ke halaman login.

Jika Anda menggunakan identitas asp.net dan otentikasi berbasis owin di sini kode yang dapat membantu menyelesaikan masalah itu:

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);
}
Manik Arora
sumber
1
saya mengubah diskriminan untuk memeriksa apakah permintaan menerima teks / html atau aplikasi / xhtml sebagai tanggapan, jika mereka tidak menganggap itu permintaan klien "otomatis", permintaan ajax
semacam itu
4
Saya lebih suka pendekatan ini juga. Satu-satunya tambahan yang saya buat adalah mengonversi LocalPath .ToLower () jika mereka meminta "/ API" atau sesuatu.
FirstDivision
1
Terima kasih banyak. Itu menyelamatkan hari saya. :)
Amit Kumar
Adakah yang beruntung dengan ini? CookieAuthenticationOptions tidak lagi memiliki properti Penyedia pada aspnet core 1.1.
Jeremy
27

Saya mendapatkan situasi yang sama ketika OWIN selalu mengarahkan respons 401 ke halaman Login dari WebApi. Web API kami mendukung tidak hanya panggilan ajax dari Angular tetapi juga Mobile, Win Form calls. Oleh karena itu, solusi untuk memeriksa apakah permintaan tersebut adalah permintaan ajax tidak benar-benar diurutkan untuk kasus kami.

Saya telah memilih pendekatan lain adalah menyuntikkan respons tajuk baru: Suppress-Redirectjika tanggapan berasal dari webApi. Implementasinya ada di handler:

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

Dan daftarkan handler ini di tingkat global WebApi:

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

Jadi, pada startup OWIN Anda dapat memeriksa apakah header respons memiliki 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;
}
cuongle
sumber
Terima kasih ! API kami bekerja di setiap bentuk plat, kecuali Xamarin / Android. Akan menggunakan solusi ini
Jurion
17

Dalam versi ASP.NET sebelumnya, Anda harus melakukan banyak hal agar ini berfungsi.

Berita baiknya adalah, karena Anda menggunakan ASP.NET 4.5. Anda bisa menonaktifkan pengalihan otentikasi formulir menggunakan properti HttpResponse.SuppressFormsAuthenticationRedirect baru .

Di Global.asax:

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

EDIT : Anda mungkin juga ingin melihat artikel ini oleh Sergey Zwezdin yang memiliki cara yang lebih halus untuk mencapai apa yang Anda coba lakukan.

Cuplikan kode yang relevan dan narasi penulis yang ditempel di bawah. Penulis asli kode dan narasi - Sergey Zwezdin .

Pertama - mari kita tentukan apakah permintaan HTTP saat ini adalah permintaan AJAX. Jika ya, kita harus menonaktifkan penggantian HTTP 401 dengan HTTP 302:

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

Kedua - mari kita tambahkan kondisi :: jika pengguna diautentikasi, maka kami akan mengirimkan HTTP 403; dan HTTP 401 sebaliknya.

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

Sudah selesai dilakukan dengan baik. Sekarang kita harus mengganti semua penggunaan standar AuthorizeAttribute dengan filter baru ini. Ini mungkin tidak berlaku untuk orang-orang sime, yang estetika kode. Tapi saya tidak tahu cara lain. Jika sudah, silakan ke komentar.

Yang terakhir, apa yang harus kita lakukan - untuk menambahkan penanganan HTTP 401/403 di sisi klien. Kita dapat menggunakan ajaxError di jQuery untuk menghindari duplikasi kode:

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

Hasil -

  • Jika pengguna tidak diautentikasi, maka ia akan diarahkan ke halaman login setelah panggilan AJAX.
  • Jika pengguna diautentikasi, tetapi tidak memiliki izin yang cukup, maka ia akan melihat pesan erorr yang ramah pengguna.
  • Jika pengguna diautentikasi dan memiliki cukup izin, maka tidak ada kesalahan dan permintaan HTTP akan diproses seperti biasa.
Siwa
sumber
Saya menggunakan kerangka identitas baru untuk auth via mvc. Apakah pengaturan ini tidak mencegah mvc login berfungsi serta panggilan webapi?
Tim
5
ketika saya memeriksa contoh ini tampaknya Atribut Otorisasi yang digunakan adalah versi MVC daripada versi WebApi. namun versi webapi tidak memiliki opsi untuk menekan formulir authentiucation.
Tim
permintaan saya tidak memiliki metode IsAjaxRequest.
Tim
1
Tim melihat ini untuk IsAjaxRequest: brockallen.com/2013/10/27/... Jika Anda menggunakan AngularJs tanpa mengedit header, Anda tidak akan memiliki "XMLHttpRequest" dan menambahkan atau memeriksa sesuatu yang lain.
Tim
10

Jika Anda menjalankan Web APIdari dalam MVCproyek Anda, Anda harus membuat kebiasaan AuthorizeAttributeuntuk diterapkan pada APImetode Anda . Di dalam IsAuthorized overrideAnda perlu mengambil arus HttpContextuntuk mencegah pengalihan, seperti ini:

    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);
    }
Serj Sagan
sumber
8

Menggunakan integrasi Direktori Aktif Azure sendiri, pendekatan menggunakan CookieAuthenticationmiddleware tidak berhasil untuk saya. Saya harus melakukan hal berikut:

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

Jika permintaan berasal dari browser itu sendiri (dan bukan panggilan AJAX, misalnya) maka header Terima akan berisi string html di suatu tempat. Hanya ketika klien menerima HTML saya akan mempertimbangkan pengalihan sesuatu yang bermanfaat.

Aplikasi klien saya dapat menangani 401 yang memberi tahu pengguna bahwa aplikasi tidak memiliki akses lagi dan perlu memuat ulang untuk masuk lagi.

Dave Van den Eynde
sumber
Ini sangat mirip dengan solusi yang diajukan untuk pertanyaan terkait: stackoverflow.com/questions/34997674/…
Guillaume LaHaye
6

Saya juga punya aplikasi MVC5 (System.Web) dengan WebApi (menggunakan OWIN) dan hanya ingin mencegah 401 tanggapan dari WebApi diubah menjadi 302 tanggapan.

Apa yang berhasil bagi saya adalah membuat versi khusus dari WebApi AuthorizeAttribute seperti ini:

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

Dan untuk menggunakannya sebagai pengganti OtorisasiAttribute WebApi standar. Saya menggunakan standar MVC AuthorizeAttribute untuk menjaga perilaku MVC tidak berubah.

Jono Job
sumber
Bekerja, tetapi sekarang saya memiliki masalah bahwa klien menerima status -1 alih-alih 401
Sebastián Rojas
@ SebastiánRojas Saya tidak yakin apa yang akan menyebabkan itu - pengaturan SuppressFormsAuthenticationRedirect bendera menyebabkannya hanya mengembalikan 401 yang ada untuk saya.
Jono Job
3

Cukup instal Paket NeGet berikut

Instal-Paket Microsoft.AspNet.WebApi.Owin

Tulis kode berikut dalam file 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"));
    }
}

sumber
Yang perlu saya lakukan adalah menambahkan filter ini dan config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));jika User.Identity.IsAuthenticatedtidak selalu berfungsifalse
Ricardo Saracino
1

jika Anda ingin menangkap Content-Type == application / json Anda dapat menggunakan kode itu:

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;

    }

salam!!

chemitaxis
sumber
1

Saya mengalami kesulitan mendapatkan kode status dan respons teks yang berfungsi dalam metode OnAuthorization / HandleUnauthorizedRequest. Ini ternyata menjadi solusi terbaik bagi saya:

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

Setelah banyak kerepotan mencoba menghindari pengalihan ke halaman login, saya menyadari bahwa ini sebenarnya cukup tepat untuk atribut Otorisasi. Dikatakan pergi dan dapatkan Otorisasi. Sebaliknya untuk panggilan Api yang tidak diotorisasi, saya hanya ingin tidak mengungkapkan informasi apa pun untuk menjadi peretas. Tujuan ini lebih mudah dicapai secara langsung dengan menambahkan atribut baru yang diturunkan dari Otorisasi yang malah menyembunyikan konten sebagai kesalahan 404:

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

Mencampur MVC dan WebAPI, jika permintaan tidak sah maka itu akan mengarahkan ulang ke halaman login bahkan dalam permintaan WebAPI juga. Untuk itu, kita dapat menambahkan kode di bawah ini untuk mengirim respons ke aplikasi seluler

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();
}
Avid Programmer
sumber
0

Terima kasih kawan!

Dalam kasus saya, saya menggabungkan jawaban cuongle & Shiva , dan mendapatkan sesuatu seperti ini:

Di pengendali OnException () pengendali untuk Pengecualian API:

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

Dalam kode konfigurasi startup Aplikasi:

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);
                }
            }
        }
    });
Chakrit W
sumber
-1

Dalam MVC 5 dengan Dot Net Framework 4.5.2 kita mendapatkan "application / json, plaint text .." di bawah tajuk "Accept". Akan menyenangkan untuk digunakan seperti berikut:

isJson = headers["Content-Type"] == "application/json" || headers["Accept"].IndexOf("application/json", System.StringComparison.CurrentCultureIgnoreCase) >= 0;
Imran Javed
sumber