none
AspNetCore.Identity Framework - Dynamisch Rollen zu Funktionen RRS feed

  • Frage

  • Hallo, ich arbeite mich zur Zeit in dieses Identity Framework ein. Wenn ich es richtig verstanden habe, muss jede Controller-Methode mit z.B. Authorize oder einer Rolle oder etwas ähnliches gesichert sein. 
    Jetzt frage ich mich, wie bildet man ein typisches Szenario aus einer Community ab, wo man nicht ständig jede Rolle fest verdrahten kann ab. Z.B. wenn ich alle Threads aus einer bestimmten Gruppe abfragen möchte. Zum einen muss er überhaupt Eingeloggt sein, zum anderen muss er Mitglied in der Gruppe sein. Aber Die Gruppe wird ja ebenfalls Dynamisch übergeben. So weiß die Methode in der Definition gar nicht ob das Mitglied autorisiert ist.

    Einfach gedacht könnte man das ja so abbilden. (Pseudocode)

    void GruppenThreads(string tolleGruppe) {

       var gruppenMigtliederList = GibGruppenmitgliederZurGruppe (tolleGruppe);

       If (gruppenMigtliederList.Contains(User) {

         GibThreadsZurück();

       }

       else {  AblehnenDaKeinMiglied }

    }

    Montag, 1. Oktober 2018 20:38

Antworten

  • Ich kenne kein Tutorial. 401 wird durch ASP.NET zurückgegeben wenn Authorize die Methode/Action schützt.

    Das obere Beispiel kann man einfach mit 1 Rolle realisieren, z.B. AdvancedUser nur dieser darf Links und Bilder posten. 

    Dem User sollte dann im Frontend alle Funktionen angezeigt werden die er nutzen darf. Wie das geht hängt vom Frontend ab. Ich entwickle nur noch Web Apis. Als Frontend nutze ich entweder native Apps oder SPA Frameworks wie Angular, Blazor, React, Vue, usw. Ich übergebe einfach an das Frontend die jeweilige Rolle des Users damit werden dann die Funktionen ein ober ausgeschaltet. Natürlich gibt das noch keine Sicherheit, User könnten durch Zufall oder einen Fehler Funktionen nutzen die nicht seiner Rolle entsprechen. Auch könnte der User direkt die Endpoints der Api aufrufen und Daten übergeben. Das ein und ausschalten von Funktionen sowie das validieren von Daten Clientseitig hat den zweck unnötige Anfragen gegen den Server zu vermeiden und bietet mehr Möglichkeiten dem User den Umgang mit der App zu "erklären". Was der User darf entscheidet in letzter Instanz der Server. 

    Serverseitig ist dies einfach zu lösen

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    using WebApi.Models;
    
    namespace WebApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        [Authorize] //Ich schütze die gesamte Klasse
        public class ForumController : ControllerBase
        {
            private readonly UserManager<AppUser> _userManager;
            private readonly SignInManager<AppUser> _signInManager;
    
            public ForumController(UserManager<AppUser> userManager)
            {
                _userManager = userManager;
            }
    
            [HttpGet("{id}")]
            [AllowAnonymous]
            public IActionResult GetThreads(string id)
            {
                //Threads ansehen darf jeder. Somit öffne ich die Methode für jeden mit AllowAnonymous
                //Suche die Daten in der DB und gebe sie zurück
    
                return Ok("Daten");
            }
    
            [HttpPost]
            public async Task<IActionResult> SaveThread(ThreadModel model)
            {
                //Hier kommt man nur rein wenn der User angemeldet ist, somit kann ich mir den User geben lassen
    
                var user = await _userManager.GetUserAsync(HttpContext.User);
    
                //Nun ist eine Prüfung durchzuführen ob Bilder und Links enthalten sind
                bool imagesOrLinksAvailable = true; //Prüfung hat ergeben das Bilder vorhanden sind
    
                if (imagesOrLinksAvailable)
                {
                    if (await _userManager.IsInRoleAsync(user, "AdvancedUser"))
                    {
                        //User is in Rolle Daten können gespeichert werden
                    }
                    else
                    {
                        //Manuelle rückgabe 401
                        return Unauthorized();
                    }
                }
                else
                {
                    //Keine Bilder oder Links, Daten können gespeichert werden
                }
    
                return Ok();
            }
        }
    
        public class ThreadModel
        {
            public string Title { get; set; }
            public string Message { get; set; }
        }
    }


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings

    • Als Antwort markiert UrielMhezzek Mittwoch, 3. Oktober 2018 08:29
    Dienstag, 2. Oktober 2018 20:24

Alle Antworten

  • Hallo,

    wenn man als Beispiel dieses Forum nimmt, habe User immer entsprechende Rechte:

    • ein anonymer User kann alles lesen sonst nichts
    • ein angemeldeter User kann lesen, abstimmten und neue Threads erfassen aber keine Bilder oder Links posten
    • ein zertifizierter angemeldeter User kann lesen, abstimmen und neue Threads mit Bilder und Links erstellen
    • usw..

    Ein anonymer User wird den Button "Stellen sie eine Frage" nicht zu sehen bekommen. Auch wenn der User es irgendwie schaffen würde auf die Seite zu kommen mit der man ein Thread erstellen kann, wird der Server die anfrage verwerfen und wahrscheinlich 401 Unauthorized zurückgeben. Es ist also nötig solche Regeln/Rechte nieder zu schreiben und sie anzuwenden. Von dynamisch kann also nicht die Rede sein. Diese Regeln stehen fest und sind auch bekannt.

    Das kann man durchaus mit Rollen realisieren muss man aber nicht. Es steht dir frei hier eine eigene Logik zu erstellen. Identity ist ein Werkzeug zur Prüfung der Identität mehr nicht.

    Du kannst mit Authorize den gesamten Controller "schützen". Du hast aber auch die Möglichkeit einzelne Methoden/Action wieder mit AllowAnonymous freizuschalten. 


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings

    Dienstag, 2. Oktober 2018 00:51
  • Kennst du zufällig ein Tutorial, welches so was abbildet. Ich frage mich gerade, wie man die "Vier Fälle" in die Tags rein packt oder wie man (manuell) eine 401 zurück gibt. 
    Dienstag, 2. Oktober 2018 18:27
  • Ich kenne kein Tutorial. 401 wird durch ASP.NET zurückgegeben wenn Authorize die Methode/Action schützt.

    Das obere Beispiel kann man einfach mit 1 Rolle realisieren, z.B. AdvancedUser nur dieser darf Links und Bilder posten. 

    Dem User sollte dann im Frontend alle Funktionen angezeigt werden die er nutzen darf. Wie das geht hängt vom Frontend ab. Ich entwickle nur noch Web Apis. Als Frontend nutze ich entweder native Apps oder SPA Frameworks wie Angular, Blazor, React, Vue, usw. Ich übergebe einfach an das Frontend die jeweilige Rolle des Users damit werden dann die Funktionen ein ober ausgeschaltet. Natürlich gibt das noch keine Sicherheit, User könnten durch Zufall oder einen Fehler Funktionen nutzen die nicht seiner Rolle entsprechen. Auch könnte der User direkt die Endpoints der Api aufrufen und Daten übergeben. Das ein und ausschalten von Funktionen sowie das validieren von Daten Clientseitig hat den zweck unnötige Anfragen gegen den Server zu vermeiden und bietet mehr Möglichkeiten dem User den Umgang mit der App zu "erklären". Was der User darf entscheidet in letzter Instanz der Server. 

    Serverseitig ist dies einfach zu lösen

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    using WebApi.Models;
    
    namespace WebApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        [Authorize] //Ich schütze die gesamte Klasse
        public class ForumController : ControllerBase
        {
            private readonly UserManager<AppUser> _userManager;
            private readonly SignInManager<AppUser> _signInManager;
    
            public ForumController(UserManager<AppUser> userManager)
            {
                _userManager = userManager;
            }
    
            [HttpGet("{id}")]
            [AllowAnonymous]
            public IActionResult GetThreads(string id)
            {
                //Threads ansehen darf jeder. Somit öffne ich die Methode für jeden mit AllowAnonymous
                //Suche die Daten in der DB und gebe sie zurück
    
                return Ok("Daten");
            }
    
            [HttpPost]
            public async Task<IActionResult> SaveThread(ThreadModel model)
            {
                //Hier kommt man nur rein wenn der User angemeldet ist, somit kann ich mir den User geben lassen
    
                var user = await _userManager.GetUserAsync(HttpContext.User);
    
                //Nun ist eine Prüfung durchzuführen ob Bilder und Links enthalten sind
                bool imagesOrLinksAvailable = true; //Prüfung hat ergeben das Bilder vorhanden sind
    
                if (imagesOrLinksAvailable)
                {
                    if (await _userManager.IsInRoleAsync(user, "AdvancedUser"))
                    {
                        //User is in Rolle Daten können gespeichert werden
                    }
                    else
                    {
                        //Manuelle rückgabe 401
                        return Unauthorized();
                    }
                }
                else
                {
                    //Keine Bilder oder Links, Daten können gespeichert werden
                }
    
                return Ok();
            }
        }
    
        public class ThreadModel
        {
            public string Title { get; set; }
            public string Message { get; set; }
        }
    }


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings

    • Als Antwort markiert UrielMhezzek Mittwoch, 3. Oktober 2018 08:29
    Dienstag, 2. Oktober 2018 20:24