[jQuery + Asp.Net Core] check attributy controlleru/akce

Webdesign, HTML, CSS, Flash, PHP, ASP, .NET, JavaScript. Kritika www stránek na Smetišti.

Moderátor: Moderátoři Živě.cz

Odeslat příspěvekod dyžon 14. 2. 2021 10:20

zdravím.
vytvářím stránky v ASP.Net Core 3.1,
na úvodní stránce jsou různé karty, které přesměrovávají do různých Areí na různé controllery a jejich akce.
některé controllery(akce) jsou chráněny attributem [Authorize].
k autorizaci uživatele používám Microsoft.AspNetCore.Identity.EntityFrameworkCore
chci použít Ajax pro přechod mezi stránkami.
<script src="~/lib/jquery-ajax-unobtrusive/jquery.unobtrusive-ajax.js"></script>
Kód: Vybrat vše
$("#page-content").on("click", ".card", function (e) {
    $("#page-content").fadeOut(500, function () {
         $("#page-content").load(cardUrl);
         $("#page-content").fadeIn(500);
    });
});

problém je, že když chci zavolat akci s attributem [Authorize], pokud není user přihlášen, načte se stránka Login, příkazem RedirectToAction() někde v balíčku Identity, což způsobí, že se stránka reloudne, což je pro mě nežádoucí a když použiju jQuery: $("#page-content").load(cardUrl), tak dostanu chybu: Failed to load resource: the server responded with a status of 401 (),
když použiju dotaz Ajaxem:
Kód: Vybrat vše
$.ajax({
   url: cardUrl,
   success: function (data, status, jqxhr) {
       console.log(data);
       console.log(status);
   },
   error: function (jqXHR, textStatus, errorThrown) {
       console.log(errorThrown);
   }
});

tak to nebere v potaz attribut[Authorize] a vrací vždy status 200, pokud soubor s pohledem existuje.
říkal jsem si, že bych před $("#page-content").load(cardUrl);
zavolal metodu, která zjistí, jestli má daná akce attribut [Authorize].
metodu jsem dal do Controlleru Account, kterej je bez attributů.
Kód: Vybrat vše
public async Task<JsonResult> JeAuthorizovano (string area, string controller, string action)
{
    var result = false;
    if(attribut [Authorize] existuje ????)
    {
        result = true;
    }
    else {
        result = False;
    }
   
    return Json(result);
}

potřeboval bych prosím poradit, jak upravit tu podmínku If.
z toho, co jsem zatím na google přečet se mi to nedaří a moc tomu nerozumím.
nebo Vás napadá jiné řešení ??
AMD FX-6300; Gigabyte 970A-DS3P; DDR3 8192MBytes; AMD Radeon HD 6700 Series
dyžon
Junior
Uživatelský avatar

Odeslat příspěvekod Wikan 14. 2. 2021 15:59

Asi jsem nepochopil, v čem je problém. Pochopil jsem správně, že load() vrací 401 a .ajax() vrací 200? To se mi nějak nezdá.
Wikan
Moderátor
Uživatelský avatar

Odeslat příspěvekod dyžon 15. 2. 2021 08:29

čau, děkuji za reakci,
hele, je to jednoduchý.
uživatel načte úvodní stránku, na které je několik karet (tag a).
každá z nich odkazuje do své vlastní Arei (/AreaX/Controller/Action)
uživatel klikne na kartu:
pokud je daná akce označena attributem [Authorize] balíček Identity díky nastavení v startup.cs přesměruje na přihlašovací stránku. browser se RELOUDNE.
v pořádku, jenže já chci, aby po načtení úvodní stránky už žádný reload nebyl a mezi stránkami chci procházet pomocí jQuery.
v _Layoutu mám: <div id="page-content">@RenderBody()</div>
v .js pak:
Kód: Vybrat vše
$("#page-content").on("click", ".card", function (e) {
    e.preventDefault();
    var href = $(this).attr("pageUrl");
    $("#page-content").fadeOut(500, function () {
        $("#page-content").load(pageUrl);
        $("#page-content").fadeIn(500);
    });
});

to znamená, že přesměrování na přihlašovací stránku musím udělat ručně.
prvně musím zjistit, jestli je pro tu akci nutné přihlášení, poté zjistím, jestli je už nějaký uživatel přihlášen a pokud ano, načtu akci,
pokud ne, načtu přihlašovací stránku.
stránka se ani jednou nereloudne a když uživatel stiskne (refreshPage, backPage, nebo nextPage) v browseru, načte se mu opět úvodní stránka s kartami.
problém ale mám v tom, že nevím, jak se zeptat (a to ani v jQuery, ani v ASP.Net Core) na to, jestli je ta akce označena attributem, popř. jakým, nebo mi stačí asi jen jestli vyžaduje přihlášení.
jestli a jaký uživatel je přihlášen zjistit dokážu.
------------------------------------------------------------------------
funkce .load() - pokud načítám stránku (akci), která vyžaduje přihlášení, v nástrojích browseru v Console se vypíše chyba Failed to load resource: the server responded with a status of 401 (),
máš pravdu, funkce $.ajax, nebo $.get, vrátí taky 401.
jen pokud v $.ajax nastavím crossDomain: true, tak se vrátí status: success.
našel jsem i nějaký řešení na googlu, v ASP.Net core pomocí filtrů, ale jsem z toho zmatenej.
potřeboval bych s tím prosím pomoci.
... snad jsem to tentokrát popsal lépe.
AMD FX-6300; Gigabyte 970A-DS3P; DDR3 8192MBytes; AMD Radeon HD 6700 Series
dyžon
Junior
Uživatelský avatar

Odeslat příspěvekod Wikan 15. 2. 2021 08:39

Spíš mi přijde, že jsi to ještě víc zamotal, než vysvětlil.
Řekl bych, že tebe nemá moc zajímat, jestli je nějaká akce označená Authorize atributem. Ale když ti jako odpověď na request přijde, že se máš přesměrovat, tak to přesměrování máš následovat a vytvořit nový request.
Wikan
Moderátor
Uživatelský avatar

Odeslat příspěvekod dyžon 15. 2. 2021 09:42

aha, tak to se omlouvám ...
myslíš jako:
Kód: Vybrat vše
statusCode: {
                    401: function () {
                        console.log("je potřeba přihlášení");
                    }
                }

jenže to v prohlížeči v Console stejně tu chybu vypíše a až potom se vypíše "je potřeba přihlášení".
mohl by jsi mi prosím uvést příklad, jak toho v jQuery dosáhnout ??
AMD FX-6300; Gigabyte 970A-DS3P; DDR3 8192MBytes; AMD Radeon HD 6700 Series
dyžon
Junior
Uživatelský avatar

Odeslat příspěvekod Wikan 15. 2. 2021 10:07

Jak dosáhnout čeho? Teď už se vážně ztrácím.
Wikan
Moderátor
Uživatelský avatar

Odeslat příspěvekod dyžon 15. 2. 2021 10:36

jasně,
jsem já ten, kdo potřebuje pomoc, ale prosím přečti si ještě jednou na co se ptám, není to zase až tak nesrozumitelné. myslím, že z toho lze poznat, o co mi jde, aniž bych to musel psát pořád dokola.
pokud je to srozumitelné opravdu jen v mé hlavě, protože se tím už nějaký čas zabývám, tak se moc omlouvám.

po tvé druhé odpovědi, což se mi zdá jako výborná cesta, to co potřebuji je jak poznám odpověď na request, že se má přesměrovat.
Ale když ti jako odpověď na request přijde, že se máš přesměrovat, tak to přesměrování máš následovat a vytvořit nový request.
AMD FX-6300; Gigabyte 970A-DS3P; DDR3 8192MBytes; AMD Radeon HD 6700 Series
dyžon
Junior
Uživatelský avatar

Odeslat příspěvekod Wikan 15. 2. 2021 11:16

Pokud ti jako odpověď na request přijde 401, tak to ale není přesměrování. To by bylo 302 či případně jiná 30x. A v takovém případě by ti v odpovědi přišlo, kam se máš přesměrovat.
Ze 401 nevíš vlastně nic, můžeš tak leda zobrazit login stránku, jejíž URL znáš.
Wikan
Moderátor
Uživatelský avatar

Odeslat příspěvekod dyžon 15. 2. 2021 12:15

přichází 401 :o/
pužívám Microsoft Visual Studio Community 2019 Verze 16.8.5
vytvořil jsem úplně nový project webová aplikace asp.net core MVC, ověření už. účty
v HomeController jsem přidal public IActionResult Login() a přidal zobrazení
přidal jsem PrvniController a vytvořil zobrazení,
přidal jsem DruhyController, akci Index jsem nastavil atribut [Authorize] a vytvořil zobrazení,
přidal jsem jquery-ajax-unobtrusive,
i do _layoutu kde jsem změnil odkazy Home/Index na Prvni/Index text Prvni
a Home/Privacy na Druhy/Index text Druhy
do startup.cs :
Kód: Vybrat vše
services.ConfigureApplicationCookie(options =>
            {
                options.LoginPath = "/Home/Login";
                options.SlidingExpiration = true;
            });

spustil jsem a všechno funguje jak má ...
do site.js jsem napsal:
Kód: Vybrat vše
$(function () {
    $("header").on("click", "li a", function (e) {
        e.preventDefault();
        var href = $(this).attr("href");
        $("main").fadeOut(500, function () {
            $.ajax({
                url: href,
                statusCode: {
                    401: function () {
                        console.log("401");
                    },
                    200: function () {
                        console.log("200");
                    },
                    404: function () {
                        console.log("404");
                    },
                    302: function () {
                        console.log("302");
                    }
                }
            });
            //$("main").load(href);
            $("main").fadeIn(500);
        });
    });
});

při kliknutí na První vše v pohodě, v Console: status code 200
při kliknutí na Druhý, v Console: status code 401.
moje otázka je, jak zjistím, že se má uživatel než načtu požadovanou stránku přihlásit.
tak snad teď .. :o))
AMD FX-6300; Gigabyte 970A-DS3P; DDR3 8192MBytes; AMD Radeon HD 6700 Series
dyžon
Junior
Uživatelský avatar

Odeslat příspěvekod Wikan 15. 2. 2021 12:30

jak zjistím, že se má uživatel než načtu požadovanou stránku přihlásit.

Ale tohle opravdu zjišťovat předem nechceš. Nejde totiž jenom o zjištění, jestli je potřeba samotné přihlášení, ale pak ještě musíš vzít úvahu, jestli už třeba uživatel prihlášený není. Nebo přihlášený je, ale na konkrétní stránku nemá dostatečná práva atd.
Potřebu přihlásit se bys měl teda zjistit z reakce serveru. Tedy buď tě rovnou odkáže na login stránku (pomocí 302) nebo se na ni holt budeš muset přesměrovat sám (když ti vrátí 401).
Wikan
Moderátor
Uživatelský avatar

Odeslat příspěvekod dyžon 15. 2. 2021 12:53

jestli je uživatel přihlášenej a jakej i jeho roli zjistím jednoduše.
do Home Controlleru přidám akci, kde pomocí IUserManageru zjistím jestli uživatel existuje a pak přes IRoleManager jakou má roli.
akci opět zavolám ajaxem.
že to není problém jsem psal už asi ve druhým příspěvku.
ano, můžu když se mi vrátí 401 načíst rovnou Login, ale to teď mám, takže to jsem se neposunul.
bohužel v Console vyskočí tahle chyba: GET https://localhost:/Prvni 401
chci tomu nějak předejít
myslel jsem, že se dá v asp.net core nějak zjistit, jaké má určitá akce atributy.
nebo že se dá nějak přímo zavolat funkce z Identity, která se o to stará.
AMD FX-6300; Gigabyte 970A-DS3P; DDR3 8192MBytes; AMD Radeon HD 6700 Series
dyžon
Junior
Uživatelský avatar

Odeslat příspěvekod Wikan 15. 2. 2021 14:04

Tak pokud jde o tu chybu v konzoli, tak ta pokud vím odstranit nejde. Ale zkusil jsem si rozjet stejný projekt jako máš ty a při vstupu na stránku s [Authorized] mi to normálně vrací 302 s odkazem na login page.
Při tom zkoušení jsem si ale uvědomil jednu věc - server ti vrací kompletní stránku a nějak nevidím rozdíl mezi tím, že se reloadne klasicky a tím, že ten kompletní obsah vyměníš pomocí JS.
Tohle se obvykle používá, když chceš nahradit jenom část stránky.
Wikan
Moderátor
Uživatelský avatar

Odeslat příspěvekod dyžon 15. 2. 2021 15:07

dík, že jsi to vyzkoušel ...
takže myslíš, že je problém v nastavení serveru, že vrací 401 ?
opět jsem brouzdal a splácal jsem něco, co zatím funguje tak jak chci.
startup.cs jsem upravil :
Kód: Vybrat vše
services.ConfigureApplicationCookie(options =>
            {
                options.Cookie.Name = "Authorize";
                options.Events.OnRedirectToLogin = StatusCodeBezReload;
                options.SlidingExpiration = true;
            });

a hned pod: public void ConfigureServices(IServiceCollection services)
jsem definoval:
Kód: Vybrat vše
internal static Task StatusCodeBezReload(RedirectContext<CookieAuthenticationOptions> context)
        {
            context.Response.StatusCode = 302;
            return Task.CompletedTask;
        }

nevím, jestli to do budoucna nebude problém, ale zatím se zdá vše v poho.
hlavne to neháže žádnou chybu. :o)
a když uživatel napíše http://doména/Druha , tak se nic nestane, respective se zobrazí bílá stránka.
vím, že obsah je stejnej při reloadu, nebo načtení ajaxem, je to spíš můj rozmar, že to tak chci, ale mám v plánu zachovávat určity data při přechodu mezi Areama.
mohl bych vytvořit model, a předávat si ho, ale chci vyzkoušet i tuto metodu.
budu testovat, kdyby byl problém, doplním info.
navíc stejně jak načítam page-content, načítám i pro každou Areu vlastni header, kterej je před page-content, takže ten rozdíl tam přece jen je.
zatím děkuji ...
AMD FX-6300; Gigabyte 970A-DS3P; DDR3 8192MBytes; AMD Radeon HD 6700 Series
dyžon
Junior
Uživatelský avatar


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků