webentwicklung-frage-antwort-db.com.de

Benutzerdefiniertes AuthorizeAttribute in der Web-API (.Net Framework) erstellen

Ich verwende OAuth2.0 Owin (Kennwortgewährung) in meiner WebAPI. Meine erste Token-Antwort lautet wie folgt

{
    "access_token": "_ramSlQYasdsRTWEWew.....................",
    "token_type": "bearer",
    "expires_in": 17999,
    "permissions": {
        "user": [
            "Add",
            "Update",
            "Delete"
        ],
        "Product": [
            "Read",
            "Create"
        ]
    }
}

Ich habe angepasst die Antwort durch das Erstellen eines neuen Schlüssels namens permissions, der die Berechtigungen für den entsprechenden Benutzer enthält.

Von hier aus muss ich jede Anforderung aus meinem Resource server validieren, indem geprüft wird, ob der Benutzer über die erforderlichen Berechtigungen verfügt, um die API mit dem Berechtigungsattribut aufzurufen.

Ich habe ein ähnliches Beispiel aus hier gefunden, wo es sich um Dot net Core handelt, was für meinen Fall nicht geeignet ist.

Der schwierige Teil ist, dass der JSON-Schlüssel permission selbst mit ArrayList einen Komplex bildet.

[CustomAuthorize(PermissionItem.Product, PermissionAction.Read)]
    public async Task<IActionResult> Index()
    {
        return View(Index);
    }

public class CustomAuthorize : AuthorizeAttribute {
    public AuthorizeAttribute (PermissionItem item, PermissionAction action) {
        //Need to initalize the Permission Enums
    }
    public override void OnAuthorization (HttpActionContext actionContext) {
        //Code to get the value from Permissions ArrayList and compare it with the Enum values
    }
}

Das obige ist die Idee, die ich habe. Aufgrund der Komplexität des Permissions-Key- und Enum-Vergleichs kann ich jedoch nicht vorankommen.

Außerdem gibt es eine Frage wie Wenn die Berechtigung für Benutzer Hinzufügen sowie Update bedeutet, dass ich vor meinem Controller zwei Attributbedingungen erstellen muss.

Mögen

[CustomAuthorize(PermissionItem.User, PermissionAction.Add)]
[CustomAuthorize(PermissionItem.User, PermissionAction.Update)]

Dies führt zum Hinzufügen weiterer Attributzeilen. Gibt es eine Möglichkeit, wie in einer einzelnen Bedingung mit | getrennt zu werden?

[CustomAuthorize(PermissionItem.User, PermissionAction.Update|PermissionAction.Add)]
9
Jayendran

Wir haben einen API-Filter für die Authentifizierung erstellt.

Hier übergeben "SecretToken", "MerchantKey" diese beiden Schlüssel, die in der API-Anforderung übergeben werden. Wir überprüfen diese beiden Daten aus der Datenbank mit der Funktion "IsValidMerchant".

IsValidMerchant Diese Funktion stellt eine direkte Verbindung zur Datenbanktabelle her, in der der jeweilige Wert gespeichert ist

public void OnAuthorization(AuthorizationFilterContext actionContext)
{
  const string secretTokenName = "SecretToken";
  const string merchentKeyName = "MerchantKey";
  bool isValid = false;

  if (!actionContext.Filters.Any(item => item is IAllowAnonymousFilter))
    {
     CPServiceResponse response = new CPServiceResponse();
     var secretToken = actionContext.HttpContext.Request.Headers[secretTokenName].FirstOrDefault();
     var merchentKey = actionContext.HttpContext.Request.Headers[merchentKeyName].FirstOrDefault();

      isValid = this.IsValidMerchant(merchentKey, secretToken,_productCode);

       if (isValid == false)
        {
          response.Status = (int)HttpStatusCode.Unauthorized;
          response.Message = Hegic.Shared.Resource.Common.UnauthorizedRequestError;
          actionContext.Result = new JsonResult("")
                {
                    Value = new { Status = response }
                };
         }
      }
  }
1
Parth Akbari

Sie könnten uns aus Flags und binären Operationen machen, damit Sie | die verschiedenen Operationen zusammen.

Der folgende Code zeigt ein kleines Beispiel, wie dies möglich ist

class Program {
    static void Main(string[] args) {
        Test test = new Test();
        CustomAuthorizeAttribute customAuthorizeAttribute = (CustomAuthorizeAttribute)Attribute.GetCustomAttribute(typeof(Test), typeof(CustomAuthorizeAttribute));

        customAuthorizeAttribute.Test();

        Console.ReadKey();
    }
}

[CustomAuthorize(PermissionActions = PermissionAction.Add | PermissionAction.Delete)]
public class Test {

}

public class CustomAuthorizeAttribute : Attribute {
    public PermissionAction PermissionActions { get; set; }

    public void Test() {
        if ((PermissionActions & PermissionAction.Add) == PermissionAction.Add) Console.WriteLine("Add");
        if ((PermissionActions & PermissionAction.Delete) == PermissionAction.Delete) Console.WriteLine("Delete");
        if ((PermissionActions & PermissionAction.Update) == PermissionAction.Update) Console.WriteLine("Update");
    }
}

public enum PermissionAction {
    Add = 1,
    Update = 2,
    Delete = 4
}

Was ergibt die folgende Ausgabe

 enter image description here

0
3dd

Warum lassen Sie nicht zu, dass Ihr CustomAuthorize-Konstruktor mehrere Berechtigungsaktionen hat.

public class CustomAuthorize : AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var currentIdentity = System.Threading.Thread.CurrentPrincipal.Identity;
        if (!currentIdentity.IsAuthenticated) {
            // redirect to access denied page
        }

        var userName = currentIdentity.Name;
        // step 1 : retrieve user object

        // step 2 : retrieve user permissions

        // step 3 : match user permission(s) agains class/method's required premissions

        // step 4 : continue/redirect to access denied page
    }
}

Und Sie kommentieren Ihre Klasse mit: [CustomAuthorize(PermissionItem.User, PermissionAction.Update, PermissionAction.Add)]

Ich bin mir nicht sicher, was OP hier erreichen will. Wenn Sie sich bei der Bereitstellung von Zugriffsrechten auf die HTTP-Anforderung verlassen, handelt es sich um A BIG SECURITY HOLE. Bei jeder Anforderung sollten Sie die Zugriffsrechte des Benutzers aus der Datenbank abrufen und dann gegen die erforderliche Berechtigung der Klasse/Methode verstoßen. 

Als Faustregel sollten Sie sich nicht auf das Anforderungsobjekt verlassen, um über die Berechtigungen zu informieren, über die der aktuelle Benutzer verfügt. Sie sollten sie aus dem Datastore abrufen.

Meine Implementierung von CustomAttribute

public class CustomAuthorize : System.Web.Http.AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    protected override Boolean IsAuthorized(HttpActionContext actionContext)
    {
        var currentIdentity = actionContext.RequestContext.Principal.Identity;
        if (!currentIdentity.IsAuthenticated)
            return false;

        var userName = currentIdentity.Name;
        using (var context = new DataContext())
        {
            var userStore = new UserStore<AppUser>(context);
            var userManager = new UserManager<AppUser>(userStore);
            var user = userManager.FindByName(userName);

            if (user == null)
                return false;

            foreach (var role in permissionActions)
                if (!userManager.IsInRole(user.Id, Convert.ToString(role)))
                    return false;

            return true;
        }
    }
}
0
Dipen Shah