9

Active Resource può utilizzare l'autenticazione HTTP impostata a livello di classe. Per esempio:È thread-safe impostare l'autenticazione HTTP Active Resource su base per utente?

class Resource < ActiveResource::Base 
end 

Resource.user = 'user' 
Resource.password = 'password' 

o

Resource.site = "http://user:[email protected]/" 

Ma cosa succede se io uso l'autenticazione HTTP diversa in base a quale utente è loggato? Se cambio Resource.user e Resource.password, ciò causerà una condizione di competizione in cui le richieste da un thread iniziano improvvisamente a utilizzare l'autenticazione di un utente le cui richieste sono eseguite simultaneamente in un thread diverso? Oppure si tratta di un problema (a condizione di reimpostare l'autenticazione tra le richieste) perché i server dei binari non sono multithread?

Anche se non ci sono problemi di sicurezza dei thread, sembra comunque rischioso che se non riesco a ripristinarli, le credenziali dell'utente precedente verranno utilizzate automaticamente dalle richieste future.

Aggiornamento: Dopo essere stato frustrato con ActiveResource, ho scritto la mia libreria RIPOSO: https://github.com/DeepWebTechnologies/well_rested

risposta

7

scimmia patchare il host, user e password metodi della ActiveResource::Base classe:

class ActiveResource::Base 
    # store the attribute value in a thread local variable 
    class << self 
    %w(host user password).each do |attr|    

     define_method(attr) do 
     Thread.current["active_resource.#{attr}"] 
     end 

     define_method("#{attr}=") do |val| 
     Thread.current["active_resource.#{attr}"] = val 
     end 
    end 
    end 
end 

Ora impostare il credenziali in ogni richiesta

class ApplicationController < ActionController::Base 

    around_filter :set_api_credentials 

private 

    # set the credentials in every request 
    def set_api_credentials 
    ActiveResource::Base.host, 
     ActiveResource::Base.user, 
     ActiveResource::Base.password = current_user_credentials 
    yield 
    ensure 
    ActiveResource::Base.host = 
     ActiveResource::Base.user = 
     ActiveResource::Base.password = nil 
    end 

    DEFAULT_HOST, DEFAULT_USER, DEFAULT_PASSWORD= [ 
    "http://www.foo.com", "user1", "user78102" ] 

    def current_user_credentials 
    current_user.present? ? 
     [ current_user.host, current_user.login, current_user.password] : 
     [ DEFAULT_HOST, DEFAULT_USER, DEFAULT_PASSWORD] 
    end 

end 
+1

Questo vuol dire che sì, non causa una condizione di competizione? O è solo una precauzione? –

+0

Sì, in modalità di produzione è possibile eseguire in condizioni di competizione se si desidera modificare il parametro di connessione per richiesta. L'utilizzo della variabile locale Thread risolve questo problema. –

+0

Ho una soluzione simile per l'impostazione di 'self.site' senza problemi di race condition http://stackoverflow.com/questions/8623204/set-site-user-fields-in-activeresource/9053643#9053643 – troex