2015-05-17 9 views
6

Possiedo un progetto .NET Mobile Servizi di Azure con alcuni controller che desidero proteggere con l'attributo Authorize tipico. Posso creare una tabella ruoli e una tabella UserProfiles e associare i vari utenti autenticati tramite Google, Facebook, ecc. Con i ruoli nella mia tabella ruoli.Aggiunta di ruoli personalizzati all'utente dei servizi mobili di Azure (Google, Twitter, Facebook, Microsoft)

La mia domanda è: come si aggiunge una richiesta di ruoli ai ServiceUser al termine dell'autenticazione ma prima che venga eseguito il metodo OnAuthorize del filtro Authorize? È possibile?

esempio di quello che voglio fare:

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

ruvido esempi tavolo:

Roles 
id | name 
1 | user 
2 | admin 

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

UserRoles (Linking Table) 
roleId | userId 
2  | 1 

Edit:

Una possibilità potrebbe essere quella di creare il mio filtro azione sovrascrivendo il filtro Autorizza attributo e nel metodo OnAuthorize è possibile interrogare le tabelle UserProfiles e Roles per ottenere i ruoli per l'utente corrente, quindi verificare i ruoli specificati in Autorizza proprietà Roles dell'oggetto per determinare se l'utente ha accesso. Ma in qualche modo, sembra che ci dovrebbe essere un posto in precedenza nella pipeline che posso intercettare per aggiungere solo le richieste dei ruoli all'utente corrente.

+0

Mi c'è voluto tutto il giorno ieri, ma ho finalmente arrivati ​​alla soluzione sotto. Ho provato di tutto, dal middleware OWIN personalizzato a LoginProviders personalizzati e nessuno mi ha ottenuto quello che volevo. Avrei potuto creare il mio AuthorizationAttribute personalizzato, ma continuavo a pensare che ci sarebbe stato un posto in precedenza nella pipeline in cui avrei potuto aggiungere le dichiarazioni di ruolo e solo essere in grado di usare il solito AuthorizeAttribute [Authorize (Roles = "User, Admin")]. La soluzione qui sotto raggiunge questo obiettivo. Ma ora so molto di più sul funzionamento interno degli assembly Microsoft.WindowsAzure. * Di quanto non avessi mai voluto. :) –

risposta

4

ho trovato la soluzione. Si tratta di:

  1. Creazione mia ServiceTokenHandler e l'override del metodo CreateServiceUser per aggiungere la logica dopo la chiamata a base.CreateServiceUser (claimsIdentity), che cerca di trovare i ruoli nella mia tabella UserProfile che sono collegati all'utente specificato in il claimIdentity. Se trova dei ruoli, aggiunge nuovi Reclami di ruolo alla raccolta Sinistri di claimsIdentity.

    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. registrare il nuovo RolesServiceTokenHandler con autofac come l'IServiceTokenHandler in modo che quando l'applicazione richiede un IServiceTokenHandler, autofac restituisce il nuovo RolesServiceTokenHandler.

All'interno metodo Register statica del file WebApiConfig.cs, modificare la chiamata a ServiceConfig.Initialize in modo che assomiglia a:

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

È possibile aggiungere la rivendicazione ruolo per l'utente principale, con qualcosa come:

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

ma poi vuoi contare su appena convalidare le informazioni richieste che ottiene in per la fornitura di autorizzazione basato ruolo?

È necessario gestire comunque l'autorizzazione e la convalida tramite AuthorizeLevelAttribute o altri attributi personalizzati per decorare i propri metodi; e che è necessario programmare il comportamento che deve essere in atto per convalidare il ruolo dell'utente. Il modo in cui convalidare l'appartenenza al ruolo deve essere fatto lì, nel metodo OnAuthorization override, e dipende da te: puoi interrogare la tua Db, Graph API, o altro. Non credo che ci sono, in questo momento, le altre opzioni di autorizzazione gestione, e la documentazione ei campioni sottolineare anche in questo modo

Ecco qualche buon riferimento:

Problemi correlati