Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

เชี่ยวชาญ Devise: คู่มือสำคัญสำหรับ Ruby on Rails Authentication

ด้วยกว่า 20,000 GitHub stars และ integrations เยอะมาก Devise gem เป็นหนึ่งใน gems ยอดนิยมที่สุดใน Ruby landscape ทำไมเราจึง term มันหนึ่งใน "hidden" gems ของ Ruby? ถึงแม้จะยอดนิยม นักพัฒนาส่วนใหญ่แค่ scratch the surface ของ capabilities ของ library

ใน series สองส่วนนี้ เราจะ deep dive เข้า Devise

ในส่วนแรก เราจะเรียนรู้ basics บางอย่าง รวมถึง:

  • Devise คืออะไร และทำไมคุณควรใช้มัน รวมถึง situations บางอย่างที่ advisable ไม่ ใช้มัน
  • วิธีติดตั้ง Devise และใช้ในโปรเจกต์
  • วิธี customize library สำหรับโปรเจกต์

ใน part two เราจะดู advanced usages ของ Devise รวมถึง:

  • OmniAuth และการใช้ Devise สำหรับ API-only applications
  • Integrating Devise กับ authorization library

มาเริ่มกัน!

Pre-requisites (ข้อกำหนดเบื้องต้น)

ใน tutorial นี้ เราจะใช้ simple Ruby on Rails 7 application ที่มี users และ tasks Users สามารถ register, log in, และ log out พร้อม access ไป create, read, update, และ delete actions สำหรับ tasks ขึ้นอยู่กับ assigned role

เราจะใช้ app นี้เพื่อ progressively build ever more complex features และใน process แสดง Devise's powerful features ใน action

มา kick off ด้วย brief introduction to Devise

แนะนำ Devise สำหรับ Ruby

Devise เป็น authentication library ที่ built on top of Warden Rack-based authentication framework

Warden จัดการ user sessions โดยใช้ secure session strings เพื่อ verify identities ของ logged-in users มันยังจัดการ users ที่ ไม่ logged in เพื่อให้แน่ใจว่าพวกเขาไม่สามารถ access restricted resources

แต่วิธีที่ Warden เป็น purely Rack-based มันไม่ add controller actions, views, helpers หรือ configuration options อื่นๆ ที่จำเป็นสำหรับการสร้าง proper user authentication solution Devise ในอีกมือทำ

คุณสมบัติ notable อีกอย่างของ Devise คือ modularity Library มาพร้อม around 10 modules ที่ให้คุณระบุได้อย่างแม่นยำว่าคุณอยากให้ authentication จัดการในแอปอย่างไร คุณไม่ต้องใช้ทั้ง 10 modules แทนที่จะ activate และใช้แค่สิ่งที่คุณต้องสำหรับแอป เราจะไป over modules นี้ภายหลัง ซึ่งรวมถึง Registerable module, Omniauthable, Trackable และอื่นๆ

ด้วยสิ่งนั้นในใจ มาเริ่มสร้าง Tasks app และติดตั้ง Devise

Getting Started: การติดตั้ง Devise

Generate new Rails 7 app โดยใช้ bundle exec rails new tasks_app หรือแค่ pull example app's code จาก repo

ให้แน่ใจว่าคุณอยู่ใน root directory ของแอป แล้วรัน bundle add devise นี่จะเพิ่ม Devise gem ไป Gemfile ของแอป หลังจากนี้ รัน bundle exec rails g devise:install เพื่อติดตั้ง Devise และ generate initializer file (เราจะดูไฟล์นี้ใกล้ชิดเมื่อเราไป through Devise's modules)

เมื่อคุณรันคำสั่งนี้ generator จะให้ setup suggestions สำหรับ Devise ให้ทำงาน as expected เพียง follow instructions ที่ให้มา และคุณควร good to go

ต่อไป มา generate user model ที่ Devise จะทำงานด้วย

Generating a Devise User Model

Devise ต้องการ user model สิ่งที่คุณเรียก model นี้ totally dependent on preferences และ use case ของแอป แต่ปกติจะเป็น User หรือ Admin

ไปข้างหน้าและ generate Devise user model ด้วย bundle exec rails g devise User นี่จะ generate User model ภายใต้ app/models/user.rb migration file เพื่อสร้าง user table และ route สำหรับ access user resource:


รัน bundle exec rails db:migrate เพื่อรัน migration และ setup user table ด้วยนั้น เราตอนนี้มี user model ที่ใช้ได้สำหรับ all things authentication

ต่อไป มา setup Task model เพื่อใช้ไปข้างหน้า

Generating a Task Model

จำได้ว่าใช้ Devise simple app ของเราต้อง:

  • Enable user เพื่อ register
  • Enable user เพื่อ sign in และ out ของแอป
  • Enable user เพื่อ create Task ที่จะ belong to them
  • Allow (หรือ disallow) user จาก interacting กับ Task ขึ้นอยู่กับ role

ด้วยนั้นในใจ มา generate Task model ที่ users จะ interact:


ตอนนี้เราควรมี Task model associated กับ user ที่สร้างมัน title, body และ status (แสดงว่าทำเสร็จหรือยัง)

หลังจากนั้น รัน bundle exec rails db:migrate เพื่อสร้าง tasks table เพิ่มเติม ให้แน่ใจว่า relate Task ไป User:


เมื่อคุณรัน scaffold generator relation belongs_to :users จะ automatically เพิ่มไปที่ Task model ทั้งหมดเดียวกัน แก้ไข Task model ให้ใช้ enum สำหรับ status ตามด้านล่าง:


ด้วยนั้น เราพร้อมที่จะดำดิ่งลึก Devise มาเริ่มด้วย brief overview ของ Devise's modules

Modules ใน Devise สำหรับ Ruby

เช่นที่กล่าวใน introduction หนึ่งใน key features ของ Devise คือ modularity แต "modularity" หมายถึงอะไรในกรณีนี้? มันเพียงแค่หมายถึง separating authentication process เข้า different parts เพื่อ managed independently

Latest version ของ Devise (at the time of writing) มี 10 modules:

  1. Database authenticatable - Module นี้จะรับ user-supplied password และ convert เป็น secure hash ซึ่งจะ stored ใน database Module ยัง handle verification เมื่อ user signs in
  2. Omniauthable - Enables OmniAuth authentication
  3. Lockable - Module นี้จะ lock account ขึ้นอยู่กับจำนวน failed logins Account ทำให้ accessible อีกครั้งหลังจาก certain time period หรือ via email
  4. Trackable - Tracks จำนวน logins ที่ account ทำ IP addresses ที่ใช้ และ login timestamps
  5. Confirmable - ส่ง email พร้อม confirmation instructions เมื่อ account registered และจะ check หาก user's account confirmed เมื่อพวกเขา log in
  6. Registerable - อนุญาต users register account บนแอป และ handles account editing และ destruction
  7. Recoverable - จัดการ password resets และ account recovery
  8. Timeoutable - Expires user sessions หลังจาก specified amount of time elapsed
  9. Validatable - ให้คุณ define custom validation rules สำหรับ user-supplied emails และ passwords ระหว่าง account creation
  10. Rememberable - ใช้ cookie เพื่อ remember user ระหว่าง authentication

สำหรับข้อมูลเพิ่มเติม Devise's documentation on modules จะ serve you well ตอนนี้เราจะ switch ไป Devise helpers และ filters

Devise Helpers และ Filters

หนึ่งใน reasons ให้ใช้ authentication library อย่าง Devise คือการ manage access ไป controller resources และ associated views Devise มา loaded พร้อม set ของ convenient helpers ซึ่งรวมถึง:

  • user_signed_in? - Check ว่ามี currently logged-in user หรือไม่
  • current_user - อนุญาตให้คุณ reference currently logged-in user ตัวอย่างเช่น คุณสามารถใช้ code snippet อย่าง current_user.email เพื่อ fetch email ของ currently logged-in user
  • user_session - สำหรับ currently logged-in user's session
  • destroy_user_session_path - Destroy logged-in user's session และ redirect ไป specified path หรือ root path
  • new_user_session_path - Respond ด้วย user login view
  • edit_user_registration_path - ให้ currently logged-in user access ไป view เพื่อ edit registration details
  • new_user_registration_path - Respond ด้วย view ที่มี registration form สำหรับ register new users

นั่นคือเรื่องของ helpers สำหรับ manage controller access Devise ให้ nifty before_action filter ที่คุณใช้ได้แบบนี้:


ด้วยนั้น มา shift focus ไปที่ Devise integrates กับ Rails' strong parameters อย่างไร

Devise และ Ruby on Rails' Strong Parameters

Strong parameters เป็น well-known Ruby on Rails feature ที่ป้องกัน mass assignment ของ request parameters ไป objects Strong parameters ต้องการ request parameters ถูก explicitly declared ก่อน assignment ใดๆ ทำได้ usually at controller level

Devise ก็ mirror functionality นี้โดย require parameters ถูก explicitly defined under appropriate Devise-specific controller actions:

  • sign_up - โดย default อยู่ใน Devise controller Devise::RegistrationsController#create Keys ที่ allowed by default คือ email, password, และ password_confirmation
  • sign_in - อยู่ใน controller Devise::SessionsController#new ด้วย default allowed authentication keys email และ password
  • account_update - อยู่ใน Devise::Registrations#update — authentication keys email, current_password, password, และ password_confirmation allowed

Most convenient way เพื่อเพิ่ม authentication keys ของคุณเองคือใช้ before_action filter ใน ApplicationController เหมือนที่นี่ ที่เราเพิ่ม username key ที่ required เมื่อ user signs up:


Interesting use case สำหรับ Devise's strong parameters คือเมื่อคุณต้อง pass array of keys ไป Devise sanitizer ตัวอย่างเช่น สมมติเรามี freelancer marketplace app ที่ user สามารถเป็น "contractor" สำหรับ hire หรือ "employer" ที่สามารถ hire contractors อื่นๆ หรือ contractor และ employer พร้อมกัน

โดยไม่ไป into too many technical details เราสามารถ achieve functionality นี้ได้โดย allow users update account โดยใช้ two select boxes สำหรับ respective roles — "contractor" และ "employer" — เพื่อให้ user สามารถเลือก either หรือ both options

Quick way ของการ achieve นี้คือใช้ array with roles as keys แต Rails' strong parameters โดย default allow only scalar values: String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, ActionDispatch::Http::UploadedFile, และ Rack::Test::UploadedFile ตามที่เห็น arrays, hashes และ objects อื่นๆ โดย default ไม่ permitted

เพื่อใช้ array ที่ permit multiple roles สำหรับ user เราสามารถ modify code ตามด้านล่าง:


Devise documentation on helpers ครอบคลุม topic ในรายละเอียดมากกว่า

ต่อไป เราจะเรียนรู้วิธี customize Devise's views และ controllers

การ Customize Devise Views

เพราะ Devise สร้างเป็น Rails engine เกือบทุก components เป็น pre-packaged Good examples ของสิ่งนี้รวมถึง views สำหรับ log in, sign up, update account details, reset password ฯลฯ ในบางจุดของ journey สร้างแอป คุณอาจต้อง customize built-in views เหล่านี้ให้ suit needs

ขั้นแรกคือ generate views โดยใช้คำสั่ง bundle exec rails g devise:views เมื่อคุณทำนั้น respective views จะ generated และ placed ใน folder app/views/devise:

เชี่ยวชาญ Devise: คู่มือสำคัญสำหรับ Ruby on Rails Authentication

มาใช้ practical example ของการ customize Devise's views ใน previous section เราเรียนรู้วิธีเพิ่ม extra authentication keys ไป Devise sanitizer มา extend example นั้นเพื่อเพิ่ม username field ไป user registration view

เนื่องจาก username field ไม่ available ให้ default user model เราจะเพิ่มมันโดยใช้ bundle exec rails g migration add_column_username_to_user username migration รันคำสั่ง bundle exec rails db:migrate เพื่อเริ่ม migration และเพิ่มคอลัมน์ไป user table

ต่อไป เปิด new user registration file และ edit ดังนี้:


Generating Devise views แบบนี้ fine หากคุณทำงานกับ all views แตพูดว่า คุณแค่อยาก customize a couple of views คุณจะทำอย่างไร? Well คุณ simply pass generator command a list ของ views ที่คุณอยากโดย indicate view flag bundle exec rails g devise:views -v sessions registrations ในกรณีนี้ นี่ only generates views associated กับ login/logout process และที่ handle sign-ups

Moving on มา dig further into Devise customization โดยเรียนรู้วิธี customize library's controllers และ routes

การ Customize Devise Controllers และ Routes

การ customize Devise's views สามารถไปได้แค่ที่ไหน หากคุณอยาก real customization คุณต้องไปเข้า library's controllers และ routes

สมมติเราอยากส่ง email ไป admin แจ้งทุก new user registration บนแอป (นี่ไม่ใช่ ideal way แตมาไปกับ example นี้เพื่อ illustrate สิ่งที่เราอยาก)

เริ่มต้น เราต้อง modify signup action ของ Devise::RegistrationsController ปกติ Devise's controllers ไม่ directly accessible สำหรับ editing ดังนั้นเหมือนที่เราทำกับ views เราสามารถ generate พวกมันได้แบบนี้:


Last bit ของคำสั่งนั้นคือ scope - ในกรณีนี้ users หากคุณอยากมันเป็นอย่างอื่น คุณสามารถ change accordingly เมื่อเสร็จ generated controllers ควรจะอยู่ใน structure คล้ายกับนี้:

เชี่ยวชาญ Devise: คู่มือสำคัญสำหรับ Ruby on Rails Authentication

ต่อไป เปิด routes file และ modify Devise's routes ให้ reflect changes ใน controller structure:


ตอนนี้เปิด Users::RegistrationsController ที่ generated ใหม่ และ modify เพื่อส่ง email ไป admin ทุกครั้งที่ new user signs up:


ตามที่เห็น ด้วย access ไป Devise's controllers และ actions คุณสามารถ modify authentication flow ของแอปได้อย่างไรก็ตาม

Coming Up Next: Advanced Use of Devise

ในส่วนแรกของ series สองส่วนนี้ เรา cover basics ของ Devise gem เราเรียนรู้ Devise's different modules และวิธี customize views และ controllers

ใน part two เราจะ dive into advanced usages ของ Devise รวมถึง API authentication และวิธีใช้ OmniAuth กับ Devise

Until then happy coding!

P.S. หากคุณต้องการอ่านโพสต์ Ruby Magic ทันทีที่เผยแพร่ ให้สมัครสมาชิก newsletter Ruby Magic ของเรา และจะไม่พลาดโพสต์เด็ดๆ ไป!