2014-11-21 3 views
5

Ich verwende den .net Claims-Principal, wenn ich einen Benutzer authentifiziere. In unserem System hat ein Benutzer mehrere Berechtigungen (kann bis zu 70 sein).Hinzufügen von mehreren Werten zu einem Benutzerantrag unter Verwendung der JSON-Zeichenfolge

Nun, anstatt die Datenbank bei jeder Anfrage abzufragen macht ein Benutzer ich dachte, es wäre gut, die Berechtigungen als Anspruch zu speichern. Ich habe versucht, jede Erlaubnis als separaten Anspruch zu speichern, aber selbst wenn ich 10 Berechtigungen erhalte, wird die Größe des Tokens enorm erhöht.

Also statt 1 Anspruch für 1 Erlaubnis hinzufügen, fragte ich mich, ob es eine andere machen würde, wenn ich alle Berechtigungen zu 1 Anspruch hinzugefügt, und es tut. Es behält die Größe des Tokens klein, aber ich habe die Berechtigungen, die ich brauche.

Um dies zu tun, musste ich alle meine Berechtigungen von einem Array in eine JSON-Zeichenfolge konvertieren und sie dann als meine Forderung speichern. Um den Anspruch zu erhalten, kann ich die Zeichenfolge dann wieder in ein Array deserialisieren und muss die Datenbank überhaupt nicht abfragen.

Ist dies in Ordnung, oder ist das eine sehr schlechte Praxis? Mache ich eine tickende Zeitbombe und es wird bald explodieren, indem ich das mache?

Beispielcode hier

var identity = new ClaimsIdentity(context.Options.AuthenticationType); 
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 

// get user permissions 
var permissions = await _permissionService.GetAllAsync(user); 

// create list of all permissions 
List<object> claimPermissions = new List<object>(); 

foreach (var item in permissions) 
{ 
    claimPermissions.Add(new 
    { 
     Action = item.Action, 
     Type = item.Type 
    }); 
} 

// convert list to json 
var json = Newtonsoft.Json.JsonConvert.SerializeObject(claimPermissions); 

// add claim 
identity.AddClaim(new Claim("Permissions", json)); 
+0

Hat jemand irgendwelche Meinungen zu diesem Thema? – Gillardo

+0

Ich möchte, dass jemand die Frage beantwortet. Vergiss den Teil "Berechtigungen" und nimm es einfach als 70+ Gegenstände. Wäre das schlecht? – Mike

Antwort

0

Es gibt eine Standard-Liste der meisten der häufig verwendeten ClaimTypes in der Klasse System.Security.Claims.ClaimTypes andI schlagen Sie diese als getrennte Ansprüche hinzuzufügen. Danach können alle verbleibenden Ansprüche als nur UserData hinzugefügt werden. Ich bin mir nicht sicher, warum Ihre App über bis zu 70 Berechtigungen verfügt. Wenn Sie Ihre Infrastruktur entwerfen, sollten Sie die Best Practices verwenden, die rollenbasierte Autorisierung verwenden. Es macht die Dinge leichter. Und denken Sie daran, dies sind bewährte Methoden. Das Windows Azure Active Directory weist dasselbe Design auf und kann dennoch jedes Authentifizierungs- und Autorisierungsszenario verarbeiten.

Wenn Sie weitere Informationen darüber benötigen, wie Sie Json Web Tokens zur Implementierung eines solchen Authentifizierungsmechanismus verwenden können, finden Sie in meinem Artikel zu diesem Thema unter here.

Gegeben ein JWT, hier ist, wie Sie überprüfen würden, ob ein Benutzer Berechtigungen hat.

private static ClaimsPrincipal ValidateToken(string token, string secret, bool checkExpiration) 
    { 
     var jsonSerializer = new JavaScriptSerializer(); 
     var payloadJson = JsonWebToken.Decode(token, secret); 
     var payloadData = jsonSerializer.Deserialize<Dictionary<string, object>>(payloadJson); 


     object exp; 
     if (payloadData != null && (checkExpiration && payloadData.TryGetValue("exp", out exp))) 
     { 
      var validTo = FromUnixTime(long.Parse(exp.ToString())); 
      if (DateTime.Compare(validTo, DateTime.UtcNow) <= 0) 
      { 
       throw new Exception(
        string.Format("Token is expired. Expiration: '{0}'. Current: '{1}'", validTo, DateTime.UtcNow)); 
      } 
     } 

     var subject = new ClaimsIdentity("Federation", ClaimTypes.Name, ClaimTypes.Role); 

     var claims = new List<Claim>(); 

     if (payloadData != null) 
      foreach (var pair in payloadData) 
      { 
       var claimType = pair.Key; 

       var source = pair.Value as ArrayList; 

       if (source != null) 
       { 
        claims.AddRange(from object item in source 
         select new Claim(claimType, item.ToString(), ClaimValueTypes.String)); 

        continue; 
       } 

       switch (pair.Key) 
       { 
        case "name": 
         claims.Add(new Claim(ClaimTypes.Name, pair.Value.ToString(), ClaimValueTypes.String)); 
         break; 
        case "surname": 
         claims.Add(new Claim(ClaimTypes.Surname, pair.Value.ToString(), ClaimValueTypes.String)); 
         break; 
        case "email": 
         claims.Add(new Claim(ClaimTypes.Email, pair.Value.ToString(), ClaimValueTypes.Email)); 
         break; 
        case "role": 
         claims.Add(new Claim(ClaimTypes.Role, pair.Value.ToString(), ClaimValueTypes.String)); 
         break; 
        case "userId": 
         claims.Add(new Claim(ClaimTypes.UserData, pair.Value.ToString(), ClaimValueTypes.Integer)); 
         break; 
        default: 
         claims.Add(new Claim(claimType, pair.Value.ToString(), ClaimValueTypes.String)); 
         break; 
       } 
      } 

     subject.AddClaims(claims); 
     return new ClaimsPrincipal(subject); 
    } 

Ich hoffe, das

Dank hilft

Stewart