iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0
自我挑戰組

Rails 手工打造自己的部落格 系列 第 22

Rails 手工打造自己的部落格 22 會員登入(下)

  • 分享至 

  • xImage
  •  

對於使用者的訊息,是 Session 跟 Cookie 都會存取的,
我們今天就要來發送 Session 跟 Cookie,
寫在 controller 裡面,

  def logining
    email = params[:user][:email]
    password = params[:user][:password]
    user = User.find_by(email: ,password: )

    if user
      # 發 session/cookie
      # Session 裡面代的參數其實可以隨便自訂,裡面我們就寫[:user]
      # 後面附的值也可以自訂,但使用 user 的 id 也比較有辨識度
      session[:user] = user.id
      redirect_to root_path, notice: '登入成功'
    else
      redirect_to login_users_path, alert: '登入失敗'
    end
  end

其實這樣就可以在伺服器端跟客戶端都儲存用戶的信息,
但其實這樣的安全性非常不足,
因為我們忘記要做一件非常重要的事情,
就是把密碼加密!

那我們要在什麼時候加密呢?
我們有需要的條件就是,只需要在註冊成功的時候加密一次,
那我們直覺上應該會寫在 create 裡面對吧,
這我們要使用比較安全的「SHA1」演算法加密,
如果寫在 create 大概是這樣吧,

  def create
    user_params[:passward] = Digest::SHA1.hexdigest(user_params[:passward])
    @user = User.new(user_params)
    
    if @user.save
      redirect_to root_path, notice: '註冊成功'
    else
      render :new
    end
  end

但一般來說,我們會把這種邏輯運算寫進 model 裡面,
以保持 controller 的乾淨,以及可讀性
做成一個 private 的 callback 方法,

callback

中文稱「回乎涵式」
一個物件的生命週期裡面分成很多個階段,
在每個 action 進行的時候,如果我們把方法放進去其中一個階段內,
意思就是我們在某個階段要呼叫這個方法,
所以才被稱為回呼,那我們只需要在一開始註冊的時候觸發加密
通常很多回呼會同名,所以以防在別的動作觸發到,
我們就用只有在create裡面才有的 before_create
那在加密學中還有一種技巧叫「鹽」,

salt 雙重加密

(Salt)
密碼學中,是指在雜湊之前將雜湊內容(例如:密碼)的任意固定位置插入特定的字串。這個在雜湊中加入字串的方式稱為「加鹽」

  before_create :encrypt_password

  def encrypt_password
         #我們在原本的密碼前後都加上字母之後再把它整個倒轉
    pw = "x#{self.password}y".reverse
                    #然後再用SHA1進行加密,達到雙重加密的效果
    self.password = Digest::SHA1.hexdigest(pw)
  end

那這樣寫進資料庫就會變成沒人懂得亂碼,就連後台工程師大概也很難推出來這個密碼,
根本沒有人知道密碼是啥,
那本人要怎麼在登入的時候寫出這個亂碼然後登入呢?
當然寫不出來!
這時後就要在他登入的時候,在傳進去判斷之前,
先對他輸入進來的東西做一樣的事情,然後再進行判斷,
我們也直接把它寫在 model,
順便把第一段的判斷式也一起搬進來

                 #這裡要給它參數讓他帶進去
  def self.login(email, password)
    return nil if email.empty? or password.empty?

    password = "x#{password}y".reverse
    password = Digest::SHA1.hexdigest(password)

    find_by email:, password:
  end

這樣我們在 controller 裡 logining 的 action 就可以再簡短

  def logining
   # 這裡就是要帶進去給他的參數
    user = User.login(
      user_params[:email],
      user_params[:password]
    )

    if user
      session[:user] = user.id
      redirect_to root_path, notice: '登入成功'
    else
      redirect_to login_users_path, alert: '登入失敗'
    end
  end

這樣我們就完成加密的動作了!!


上一篇
Rails 手工打造自己的部落格 21 - 會員登入(上)
下一篇
Rails 手工打造自己的部落格 23 - 資料關聯性
系列文
Rails 手工打造自己的部落格 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
afgn
iT邦新手 5 級 ‧ 2024-01-24 14:15:21

請問你有Github原始碼嗎? 我照你的方法做,但是一直有錯誤 >"<

我要留言

立即登入留言