Incorporating Devise Authentication into an alread

2019-03-16 04:09发布

问题:

I have a fully functional authentication system with a user table that has over fifty columns. It's simple but it does hash encryption with salt, uses email instead of usernames, and has two separate kinds of users with an admin as well.

I'm looking to incorporate Devise authentication into my application to beef up the extra parts like email validation, forgetting passwords, remember me tokens, etc... I just wanted to see if anyone has any advice or problems they've encountered when incorporating Devise into an already existing user structure. The essential fields in my user model are:

  t.string    :first_name, :null => false
  t.string    :last_name, :null => false
  t.string    :email, :null => false
  t.string    :hashed_password
  t.string    :salt
  t.boolean   :is_userA, :default => false
  t.boolean   :is_userB, :default => false
  t.boolean   :is_admin, :default => false
  t.boolean :active, :default => true
  t.timestamps

For reference sake, here's the Devise fields from the migration:

  t.database_authenticatable :null => false
  t.confirmable
  t.recoverable
  t.rememberable
  t.trackable

  add_index "users", ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true
  add_index "users", ["email"], :name => "index_users_on_email", :unique => true
  add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true

That eventually turn into these actual fields in the schema:

t.string   "email",                               :default => "", :null => false
t.string   "encrypted_password",   :limit => 128, :default => "", :null => false
t.string   "password_salt",                       :default => "", :null => false
t.string   "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string   "reset_password_token"
t.string   "remember_token"
t.datetime "remember_created_at"
t.integer  "sign_in_count",                       :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string   "current_sign_in_ip"
t.string   "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"

What do you guys recommend? Do I just remove email, hashed_password, and salt from my migration and put in the 5 Devise migration fields and everything will be OK or do I need to do something else?

EDIT:

I've started to attempt this myself and have already run into some problems. I added the devise migration fields I showed above to my existing user model, and now when I run my seeds file it gives me this Postgresql error:

ERROR: duplicate key value violates unique constraint "index_users_on_email"

My seeds file:

initial_usersA = User.create!(
[
{
    :first_name => "John", 
    :last_name => "Doe",
    :email => "johndoe@gmail.com",
    :is_userA => true,
    :is_userB => false,
            :is_admin => true,
    :password => "password",
    :password_confirmation => "password"
},
{
    :first_name => "Jane", 
    :last_name => "Smith",
    :email => "janesmith@gmail.com",
    :is_userA => true,
    :is_userB => false,
            :is_admin => true,
    :password => "password",
    :password_confirmation => "password"
}

User model:

devise :registerable, :authenticatable, :recoverable,
     :rememberable, :trackable, :validatable
attr_accessor :password_confirmation, :email, :password

The stack trace shows that the email apparently isn't being fed in with the rest of the variables for some reason... though everything else in the seed file shows up in the actual query, the email is '' for some reason even though it's explicitly defined.auth

回答1:

The two main considerations I recall we faced when we did a similar thing were:

Database Migrations - rather than using the t.database_authenticatable helpers, we wrote individual add_column and rename_column statements, so that we didn’t run into any duplicate column or index errors that you’ve see, and so so that we could reuse our salt & hashed passwords within Devise without having to modify how the gem works.

The second, and larger, consideration, was that the hashing algorithm we used was not the same as any that Devise provided, and so we had to write our own encryptor class as subclass of Devise::Encryptors::Base, and implement the digest function using our own logic. Finally, we configured Devise to use this encryptor by specifying it in the appropriate config/initializer file with config.encryptor = :our_own_algorithm

I hope this gives you enough to get you started.



回答2:

i'd get rid of the :default => "" in your schema for email. devise puts a unique constraint on email by default, so you don't want defaults of empty string



回答3:

I switched over an app from authLogic (I think) to Devise last year and my lessons were: - User table can stay - Rename columns to Devise standards, I'm sure this shouldn't be necessary, but unlike other authentication methodss, I didn't find a lib mapping file where I could add different db field names in as I have done with other authentication methods.

That was actually about it. I was really suprised about how little I needed to do. I think my hashes actually still worked or I changed to routine as directed in the instruction.

I use the 'admin' flag route with Devise so doing a sql conversion from whatever is used currently can do that.

I would also get rid of the default "" bit, I have a production app (not sure what authentication it uses, some base64 thing I think) and that looks like: t.string "EMAIL", :limit => 64, :null => false t.string "PASSWORD", :limit => 64, :null => false