Prevenire la registrazione di login riservate

Ogni volta che si realizza una web application dove gli utenti possono registrarsi, è buona cosa escludere alcuni username o login in modo che non possano essere utilizzati.
Un esempio classico è la login “admin”.
Credo che nessuno desideri che sulla sua applicazione ci sia un utente iscritto con lo username “admin” che possa magari contattare gli altri utenti spacciandosi per il vero amministratore del sito.
La stessa cosa può valere per lo username “root” e per molti altri.

E’ quindi necessario definire una lista di nomi riservati.
Fortunatamente sviluppando in Ruby on Rails è molto semplice implementare questa funzionalità sfruttando il validatore validates_exclusion_of se si utilizza Rails fino alla versione 2.3.8

1
2
3
4
5
class User < ActiveRecord::Base
  validates_exclusion_of :login,
    :in => ["admin", "root", "administrator", "superuser"],
    :message => "is reserved"
end

oppure utilizzando validates con il parametro :exclusion se si utilizza Rails 3.x

1
2
3
4
5
class User < ActiveRecord::Base
validates :login,
            :exclusion => {:in => ["admin", "root", "administrator", "superuser"],
                           :message  => "is reserved" }
end

In questo modo, chiunque tenti di creare un account con login “admin” ottiene un messaggio di errore che indica che il nome è riservato.
Va però tenuto presente che validates_exclusion_of e anche validates :exclusion sono metodi case sensitive.
Ciò significa che con questa prima implementazione un utente che provi a registrarsi come “Admin” avrà successo.

Per ovviare anche a questo problema la cosa più semplice da fare è aggiungere un before_filter prima delle validazioni che converta la login inserita in lettere minuscole.
Ecco quindi la soluzione completa per Rails 2.3.x:

1
2
3
4
5
6
7
8
9
class User < ActiveRecord::Base
 
  before_validation { |u| u.login.downcase! }
 
  validates_exclusion_of :login,
    :in => ["admin", "root", "administrator", "superuser"],
    :message => "is reserved"

end

e l’equivalente soluzione per Rails 3:

1
2
3
4
5
6
7
8
9
class User < ActiveRecord::Base

  before_validation { |u| u.login.downcase! }
 
  validates :login,
            :exclusion => {:in => ["admin", "root", "administrator", "superuser"],
                           :message  => "is reserved" }

end

Questo metodo ha però lo svantaggio di convertire tutte le login in lettere minuscole non permettendo di fatto la registrazione di due login “uguali” ma con case diverso.
Soluzione che può essere accettabile in molti casi.
Tuttavia se si ha necessità di preservare la login con maiuscole e minuscole come viene inserita dagli utenti si può sempre implementare un metodo di validazione custom:

1
2
3
4
5
6
7
8
9
class User < ActiveRecord::Base
  validate :excluded_login

  def excluded_login
    %w( admin root administrator superuser ).each do |reserved_login|
      user.errors.add(:login, "is reserved") if user.login.downcase == reserved_login
  end

end

Avete mai implementato una soluzione di questo genere? Conoscete un modo migliore di realizzarla?

Tags: , , , , ,


About Claudio

Claudio Marai is a co-founder of DevInterface.

After graduating in Computer Science has contributed to develop complex web applications based on Java/J2EE and desktop applications with the. NET framework for the Ministry of Justice and ultimately for the banking ambit.

The passion for web in recent years has led him to be interested in more modern frameworks such as Ruby on Rails and Django, and to a development approach based on agile methodologies such as eXtreme Programming and SCRUM.

About DevInterface

We are an information and communication technology agency. Our mission is to provide web application development, design services and communication strategies. We specialize in building web applications with modern and efficient frameworks.

Related Post

5 Responses to “Prevenire la registrazione di login riservate”

  1. Nicolas Blanco scrive:

    If you write custom validations that you may reuse in other projects, a great thing is to use ActiveModel::Validator (Rails >= 3) and create your own validation classes.

    http://api.rubyonrails.org/classes/ActiveModel/Validator.html

  2. Justin Baker scrive:

    Maybe try..

    class User RESERVED_NAMES,
    :message => “is reserved”

    end

  3. Justin Baker scrive:

    whoops, forgot to highlight code

    1
    2
    3
    4
    5
    6
    7
    8
    class User < ActiveRecord::Base
      RESERVED = %w{admin root administrator superuser}.collect{|n| [n,n.capitalize]}.flatten

    validates_exclusion_of :login,
        :in => RESERVED,
        :message => "is reserved"

    end
  4. Pete Roome scrive:

    Nice post, thanks for the heads up. For some reason i had’nt really considered this into the build of my app.

  5. Pixoo scrive:

    Your method could also be written like this:

    1
    2
    3
    4
    5
    def excluded_login
      if %w( admin root administrator superuser ).include?(user.login.downcase)
        user.errors.add(:login, "is reserved")
      end
    end

Leave a Reply

Insert code beetween <code lang="ruby"> and </code>

Copyright 2012 DevInterface s.n.c.

DevInterface Blog is proudly powered by WordPress