2015-05-17 8 views
6

Mam projekt usługi .NET Azure Mobile Services z niektórymi kontrolerami, które chcę zabezpieczyć za pomocą typowego atrybutu Authorize. Mogę utworzyć tabelę ról i tabelę UserProfiles oraz powiązać różnych użytkowników uwierzytelnionych przez Google, Facebook itp. Z rolami w mojej tabeli ról.Dodawanie niestandardowych ról do użytkownika usług mobilnych Azure (Google, Twitter, Facebook, Microsoft)

Moje pytanie brzmi: Jak dodać roszczenia ról do ServiceUsers po zakończeniu uwierzytelniania, ale przed uruchomieniem metody OnAuthorize filtra autoryzacji? Czy to możliwe?

Przykład tego, co chcę zrobić:

[Authorize(Roles = "admin")] 
public async Task<IHttpActionResult> Put(int id, MyDto dto){...} 

Szorstkie przykłady tabela:

Roles 
id | name 
1 | user 
2 | admin 

UserProfiles 
id | externalLoginId   | favoriteColor 
1 | Google:<ServiceUser.Id> | blue 

UserRoles (Linking Table) 
roleId | userId 
2  | 1 

Edit:

Jedną z opcji może być tworzenie mój własny filtr działania przesłanianie filtru Autoryzuj atrybut i w metodzie OnAuthorize mogłem zapytać o tabele UserProfiles i Roles, aby uzyskać role dla bieżącego użytkownika, a następnie sprawdzić względem ról określonych w polu Authorize właściwość Roles obiektu, aby określić, czy użytkownik ma dostęp. Ale wydaje się, że powinno być miejsce wcześniej w potoku, które mogę przechwycić, aby dodać roszczenia ról do bieżącego użytkownika.

+0

zajęło mi cały dzień wczoraj, ale w końcu przybył do rozwiązania poniżej. Próbowałem wszystkiego, od niestandardowego oprogramowania OWIN do niestandardowych LoginProviders i nie dostałem tego, czego chciałem. Mógłbym stworzyć własną niestandardową AuthorizationAttribute, ale ciągle myślałem, że musi być miejsce na wcześniejszym etapie, w którym mógłbym tylko dodać roszczenia do roli i po prostu móc używać zwykłego AuthorizeAttribute [Authorize (Roles = "User, Admin")]. Poniższe rozwiązanie osiąga ten cel. Ale teraz wiem więcej o wewnętrznych działaniach zestawów Microsoft.WindowsAzure. * Niż kiedykolwiek chciałem. :) –

Odpowiedz

4

Znalazłem rozwiązanie. Polega ona na:

  1. Tworzenie własną ServiceTokenHandler i przesłanianie metody CreateServiceUser dodawania logiki po wywołaniu base.CreateServiceUser (claimsIdentity), który próbuje znaleźć role w moim stole UserProfile, które są połączone do użytkownika określonego w roszczeniaIdentity. Jeśli znajdzie role, dodaje nowe roszczenia ról do zbioru roszczeń claimIdentity.

    public class RolesServiceTokenHandler : ServiceTokenHandler 
    { 
        public RolesServiceTokenHandler(HttpConfiguration config) : base(config) 
        { 
    
        } 
    
        public override ServiceUser CreateServiceUser(ClaimsIdentity claimsIdentity) 
        { 
         var serviceUser = base.CreateServiceUser(claimsIdentity); 
    
         if (serviceUser != null && serviceUser.Identity.IsAuthenticated) 
         { 
          var dataContext = new AllergenDerivativesContext(); 
          var userId = serviceUser.Id; 
          var userProfile = dataContext.UserProfiles.Include(u => u.Roles).FirstOrDefault(u => u.ExternalUserId == userId); 
    
          if (userProfile == null) 
          { 
           //If the user profile does not exist, then create it and assign it to the User role by default. 
           userProfile = new UserProfile(); 
    
           //Set the ExternalUserId for the UserProfile to the current User's External Login Id. 
           userProfile.ExternalUserId = userId; 
    
           //Get the "User" Role Entity. 
           var userRole = dataContext.Roles.FirstOrDefault(r => r.Name == Roles.User); 
    
           //Initialize the roles collection for the new UserProfile 
           //And add the existing role to the collection. 
           userProfile.Roles = new List<Role> { userRole }; 
    
           //Add the new UserProfile to the database and save the changes. 
           dataContext.UserProfiles.Add(userProfile); 
           dataContext.SaveChanges(); 
          } 
    
          //Get the roles for the UserProfile and add role claims to the ServiceUser's primary Identity. 
          foreach (var role in userProfile.Roles) 
          { 
           ((ClaimsIdentity)serviceUser.Identity).AddClaim(new Claim(ClaimTypes.Role, role.Name)); 
          } 
         } 
    
         return serviceUser; 
        } 
    } 
    
  2. Rejestracja nowego RolesServiceTokenHandler z autofac jako IServiceTokenHandler tak, że gdy aplikacja żąda IServiceTokenHandler, autofac zwraca nową RolesServiceTokenHandler.

Wewnątrz metody statycznej zarejestrować plik WebApiConfig.cs, należy zmienić wywołanie ServiceConfig.Initialize tak, że wygląda tak:

HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options, (httpConfig, autofac) => 
      { 
       autofac.RegisterType<RolesServiceTokenHandler>().As<IServiceTokenHandler>(); 
      })); 
1

Możesz dodać Claim rolę Zleceniodawcy użytkownika, coś jak:

new ClaimsIdentity(new Claim[] 
{ 
    new Claim(ClaimTypes.NameIdentifier, loginName), 
    new Claim(ClaimTypes.Role, "admin"), 
}; 

ale wtedy można liczyć na to sprawdzanie informacji twierdzi, że dostaje się do zapewnienia autoryzacji opartej na rolach?

Musisz mimo wszystko obsłużyć autoryzację i zatwierdzenie poprzez AuthorizeLevelAttribute lub inny niestandardowy atrybut, aby udekorować swoje metody; i musisz zaprogramować zachowanie, które musi być stosowane, aby sprawdzić rolę użytkownika. Sposób sprawdzania poprawności członkostwa w roli należy wtedy wykonać w trybie nadpisania metody, a to zależy od Ciebie: możesz zapytać o Db, Graph API lub inne. Nie sądzę, że istnieje w tej chwili inne opcje zezwolenia zarządzającego, a dokumentacja oraz próbki wskazują również w ten sposób

Oto niektóre dobre referencje:

Powiązane problemy