rails7: 前台用户 users/登录/注册 - 非 API 版本

利用rails的 has_secure_password 来开发登录,注册功能
更新于: 2023-12-09 11:21:01

需求

  • 前台用户表: users
  • 用户登录功能,配合 sessions 资源的操作概念
  • rails session的使用(注意: 与上面的 sessions 一点关系没有)

在Gemfile中添加 bcrypt

gem 'bcrypt', '~> 3.1.7'

生成 users

rails generate resource User username:string password_digest:string
rails
rails db:migrate

最关键的路由

查看自定义路由: rails routes | grep -v /rails/

# 理论上
rails generate controller Users new create
rails generate controller Sessions new create destroy

# 实际上,我们用一步实现即可
rails g resource User username:string password_digest:string
# 带上 conroller 一起创建
rails g resource User username:string password_digest:string
rails g controller Users new create
# 需要删除 create 这个产生的 view
rails generate controller Sessions new create destroy
功能路由
注册 - users
resources :users, only: [:new, :create]
注册页面
get '/register', to: 'users#new'
注册 post
get '/register', to: 'users#create'
登录相关 - sessions
resources :sessions, only: [:new, :create, :destroy]
登录页面
get '/login', to: 'sessions#new'
登录 post
post '/login', to: 'sessions#create'
登出 logout
delete '/logout', to: 'sessions#destroy'
我的路由表

路由最终定义

Rails.application.routes.draw do
  root "pages#welcome"
  resources :users, only: [:show, :create]
  resources :sessions, only: [:create]

  get 'signup' => 'users#new'
  get 'login' => 'sessions#new'
  delete 'logout' => 'sessions#destroy'
  get "up" => "rails/health#show", as: :rails_health_check
end

登录表单

文件位置 app/views/sessions/new.html.erb

<h1>Sessions#new</h1>
<h2>Login</h2>

<%= form_with(model: @user, url: sessions_path) do |form| %>
  <p>
    <%= form.label :username %>
    <%= form.text_field :username %>
  </p>

  <p>
    <%= form.label :password %>
    <%= form.password_field :password %>
  </p>
  <p>
    <%= form.submit "Login" %>
  </p>
<% end %>

注册表单

文件位置 app/views/users/new.html.erb

<h1>Users#new</h1>

<%= form_with(model: @user, url: users_path) do |form| %>
  <p>
    <%= form.label :username %>
    <%= form.text_field :username %>
  </p>
  <p>
    <%= form.label :password %>
    <%= form.password_field :password %>
  </p>
  <p>
    <%= form.label :password_confirmation %>
    <%= form.password_field :password_confirmation %>
  </p>
  <footer>
    <%= form.submit "Register" %>
  </footer>
<% end %>

sessions

文件 app/controllers/sessions_controller.rb

# app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  def new
  end

  def create
    user = User.find_by(username: params[:session][:username])

    if user && user.authenticate(params[:session][:password])
      # 登录成功
      session[:user_id] = user.id
      redirect_to root_path, notice: '登录成功!'
    else
      # 登录失败
      flash.now[:alert] = '用户名或密码错误'
      render :new
    end
  end

  def destroy
    # 注销
    session[:user_id] = nil
    redirect_to root_path, notice: '已注销'
  end
end

users_controller

# app/controllers/users_controller.rb

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      session[:user_id] = @user.id
      redirect_to root_path, notice: '注册成功!'
    else
      render :new
    end
  end

  private

  def user_params
    params.require(:user).permit(:username, :password, :password_confirmation)
  end
end

要不要用 profile

推荐不要改成 profile 的形式

# 用 profile
get 'profile/:id' => 'users#show', as: :profile
# 路由 profile/3
# path: profile_path(user)

# 不用的情况
resources :users, only: [:show, :create]
# 路由 users/3
# path: user_path(user)

参考