--devise is a gem that allows you to easily add authentication to your Rails application. devise is a wrapper for Rack middleware called warden, and the actual authentication is done by warden (so if you want to know the implementation details, first implement warden. I think I need to see it). --In the Rails tutorial, the authentication function is created by scratching, but in the actual Rails application, it seems that creating the authentication function using this devise is the de facto standard.
――This time, for my own study, I would like to organize how to use devise to add authentication function to Rails application. The content is almost the same as this article. Xie Xie
--All of the following implementations can be found in this repository.
# Devise
gem 'devise'
2.bundle install
$bundle install
$ rails g devise:install
create config/initializers/devise.rb
create config/locales/devise.en.yml
===============================================================================
Depending on your application's configuration some manual setup may be required:
1. Ensure you have defined default url options in your environments files. Here
is an example of default_url_options appropriate for a development environment
in config/environments/development.rb:
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
In production, :host should be set to the actual host of your application.
* Required for all applications. *
2. Ensure you have defined root_url to *something* in your config/routes.rb.
For example:
root to: "home#index"
* Not required for API-only Applications *
3. Ensure you have flash messages in app/views/layouts/application.html.erb.
For example:
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
* Not required for API-only Applications *
4. You can copy Devise views (for customization) to your app by running:
rails g devise:views
* Not required *
===============================================================================
config/development.rb
Rails.application.configure do
~~Omission~~
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
end
You can skip this and set any page as the root page.
$rails g controller StaticPages index
route.rb
Rails.application.routes.draw do
root 'static_pages#index'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
<!DOCTYPE html>
<html>
<head>
<title>DeviseRails5</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
</html>
$ rails g devise:views
invoke Devise::Generators::SharedViewsGenerator
create app/views/devise/shared
create app/views/devise/shared/_error_messages.html.erb
create app/views/devise/shared/_links.html.erb
invoke form_for
create app/views/devise/confirmations
create app/views/devise/confirmations/new.html.erb
create app/views/devise/passwords
create app/views/devise/passwords/edit.html.erb
create app/views/devise/passwords/new.html.erb
create app/views/devise/registrations
create app/views/devise/registrations/edit.html.erb
create app/views/devise/registrations/new.html.erb
create app/views/devise/sessions
create app/views/devise/sessions/new.html.erb
create app/views/devise/unlocks
create app/views/devise/unlocks/new.html.erb
invoke erb
create app/views/devise/mailer
create app/views/devise/mailer/confirmation_instructions.html.erb
create app/views/devise/mailer/email_changed.html.erb
create app/views/devise/mailer/password_change.html.erb
create app/views/devise/mailer/reset_password_instructions.html.erb
create app/views/devise/mailer/unlock_instructions.html.erb
rails g devise User
The above command will generate the following migration files.
db/migrate/20200622180124_devise_create_users.rb
# frozen_string_literal: true
class DeviseCreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
# t.integer :sign_in_count, default: 0, null: false
# t.datetime :current_sign_in_at
# t.datetime :last_sign_in_at
# t.inet :current_sign_in_ip
# t.inet :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
It seems that database_authenticatable, registerable, recoverable, rememberable and validatable are turned on by default.
app/models/user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
end
This time, we will create it with the default, but you can optionally enable any of the 10 modules.
module | Overview |
---|---|
Database Authenticatable | Hash the password and store it in the database to verify the authenticity of the user during sign-in. Authentication can be done with both POST request or HTTP basic authentication. |
Omniauthable | OmniAuth(https://github.com/omniauth/omniauth)Add support. |
Confirmable | Send an email with verification instructions to see if your account has already been verified at sign-in. |
Recoverable | Resets the user's password and sends a reset instruction. |
Registerable | Process user sign-up through the registration process, allowing users to edit and destroy their account. |
Rememberable | Manages the generation and clearing of tokens to remember users from stored cookies. |
Trackable | Keep track of sign-ins, time stamps, and IP addresses.. |
Timeoutable | Expires sessions that have been inactive for the specified time period. |
Validatable | Provides email and password verification. This is optional and customizable so you can define your own validation. |
Lockable | Locks the account after the specified number of failed sign-in attempts. Can be unlocked by email or after a specified time period |
$ rake db:migrate
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>DeviseSampleApp</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<header>
<nav>
<% if user_signed_in? %>
<%= link_to 'Profile change', edit_user_registration_path %>
<%= link_to 'Log out', destroy_user_session_path, method: :delete %>
<% else %>
<%= link_to 'Sign up', new_user_registration_path %>
<%= link_to 'Login', new_user_session_path %>
<% end %>
</nav>
</header>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
</html>
――When you access the top page, a screen like this is generated.
--Click sign up
――When you signed up and entered your email address and password, you were able to log in successfully!
user_signed_in?
You can check if the user is logged in.
current_user
You can access the logged-in user.
user_session
You can access the session.
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def after_sign_up_path_for(resource)
edit_user_registration_path #You can edit here and jump to any page
end
end
After signing up, I am now redirected to the following page.
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
edit_user_registration_path #You can edit here and jump to any page
end
end
--It seems that after_fetch is the only callback that devise calls (citation needed), so if you want to call other callbacks, use warden interface. Must be called directly.
Recommended Posts