Upgrade to Pro — share decks privately, control downloads, hide ads and more …

データ移行とdevise

Avatar for Diverseas Diverseas
December 08, 2017

 データ移行とdevise

diverseas開発ログ

Avatar for Diverseas

Diverseas

December 08, 2017
Tweet

More Decks by Diverseas

Other Decks in Technology

Transcript

  1. (C) Diverseas inc. LTͷτϐοΫ Έ͠Ζͬͪ,͔Ί͍͚͞Μ ʮϑϧεΫϥονͰॻ͖௚ͦ͏ʯ 10 1 2 3

    झຯͰ̍೥લ͔Β։ൃΛ࢝Ίɺݱࡏ1000ϢʔβʔΛಥഁ ๭౤ࢿՈ ʮ͡Ό͋౤ࢿ͢Δ͔ΒΑΖ͘͠ɻձࣾ࡞͓͍ͬͯͯɻʯ
  2. (C) Diverseas inc. എܠ 12 Frontend Authentic ation Session Routing

    ύεϫʔυ ύεϫʔυ + OAuth2 GoriGoriͷjQuery ReactͰSPA Browserେ޷͖Cookie BackendͰToken Header ࣗલͷsessionίϯτϩʔϥ ?
  3. (C) Diverseas inc. Deviseͷத਎Λͪΐͬͱ͚ͩ঺հ 14 Deviseͷ༇շͳϞδϡʔϧୡ ػೳ ֓ཁ database_authenticatabl e

    hashes and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication. registerable handles signing up users through a registration process, also allowing them to edit and destroy their account. recoverable resets the user password and sends reset instructions. rememberable resets the user password and sends reset instructions. trackable tracks sign in count, timestamps and IP address. validatable provides validations of email and password. It's optional and can be customized, so you're able to define your own validations. confirmable sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in. lockable locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period. timeoutable expires sessions that have not been active in a specified period of time. omniauthable adds OmniAuth (https://github.com/omniauth/omniauth) support.
  4. (C) Diverseas inc. Deviseͷத਎Λͪΐͬͱ͚ͩ঺հ 15 ͜Μͳײ͡ͰϞσϧͰdeviseϝιουΛ૸ΒͤΔͱ֦ு͢Δ͜ͱ͕ग़དྷ·͢ɻ class User < ApplicationRecord

    devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :omniauthable end
  5. (C) Diverseas inc. Deviseͷத਎Λͪΐͬͱ͚ͩ঺հ 17 Devise::Modelsͷதʹdeviseϝιου! ͜͜ͰϞδϡ-ϧΛ଍͢͜ͱ͕Ͱ͖Δ! https://github.com/plataformatec/devise/blob/master/lib/devise/models.rb module Devise

    module Models def devise(*modules) options = modules.extract_options!.dup selected_modules = modules.map(&:to_sym).uniq.sort_by do |s| Devise::ALL.index(s) || -1 # follow Devise::ALL order end devise_modules_hook! do include Devise::Models::Authenticatable selected_modules.each do |m| mod = Devise::Models.const_get(m.to_s.classify) if mod.const_defined?("ClassMethods") class_mod = mod.const_get("ClassMethods") extend class_mod if class_mod.respond_to?(:available_configs) available_configs = class_mod.available_configs available_configs.each do |config| next unless options.key?(config) send(:"#{config}=", options.delete(config)) end end end include mod end self.devise_modules |= selected_modules options.each { |key, value| send(:"#{key}=", value) } end end end end
  6. (C) Diverseas inc. Deviseͷத਎Λͪΐͬͱ͚ͩ঺հ 18 ͜ͷঢ়ଶͰRoutingΛݟͯΈΔͱʁ class User < ApplicationRecord

    devise :database_authenticatable, :rememberable, :trackable, :omniauthable #:recoverable,ɹ:registerable end
  7. (C) Diverseas inc. Deviseͷத਎Λͪΐͬͱ͚ͩ঺հ 19 $ rake routes eiji ~/Diverseas/Diverseas10:45PM

    >> rake routes (git)-[e346m/fb- auth]- Prefix Verb URI Pattern Controller#Action root GET / home#index new_api_v1_user_session GET /api/v1/auth/sign_in(.:format) api/v1/auth/sessions#new api_v1_user_session POST /api/v1/auth/sign_in(.:format) api/v1/auth/sessions#create destroy_api_v1_user_session DELETE /api/v1/auth/sign_out(.:format) api/v1/auth/sessions#destroy api_v1_auth_validate_token GET /api/v1/auth/validate_token(.:format) devise_token_auth/ token_validations#validate_token api_v1_auth_failure GET /api/v1/auth/failure(.:format) api/v1/auth/ omniauth_callbacks#omniauth_failure GET /api/v1/auth/:provider/callback(.:format) api/v1/auth/ omniauth_callbacks#omniauth_success GET|POST /api/v1/auth/omniauth/:provider/callback(.:format) api/v1/auth/ omniauth_callbacks#redirect_callbacks api_v1_auth_omniauth_failure GET|POST /api/v1/auth/omniauth/failure(.:format) api/v1/auth/ omniauth_callbacks#omniauth_failure GET /api/v1/auth/:provider(.:format) redirect(301) api_v1_users GET /api/v1/users(.:format) api/v1/users#index api_v1_user GET /api/v1/users/:id(.:format) api/v1/users#show
  8. (C) Diverseas inc. Deviseͷத਎Λͪΐͬͱ͚ͩ঺հ 20 ͜ͷঢ়ଶͰRoutingΛݟͯΈΔͱʁ class User < ApplicationRecord

    devise :database_authenticatable, :rememberable, :trackable, :omniauthable :recoverable,ɹ:registerable end
  9. (C) Diverseas inc. Deviseͷத਎Λͪΐͬͱ͚ͩ঺հ 21 registableͱ͔recoverableΛmodelͱ͔ʹ௥Ճ͢ΔͱRoutingͱ͔ࣗಈͰ͚ͭͯ͘ΕΔʂ eiji ~/Diverseas/Diverseas10:46PM >> rake

    routes (git)-[e346m/fb-auth]- Prefix Verb URI Pattern Controller#Action root GET / home#index new_api_v1_user_session GET /api/v1/auth/sign_in(.:format) api/v1/auth/sessions#new api_v1_user_session POST /api/v1/auth/sign_in(.:format) api/v1/auth/sessions#create destroy_api_v1_user_session DELETE /api/v1/auth/sign_out(.:format) api/v1/auth/sessions#destroy new_api_v1_user_password GET /api/v1/auth/password/new(.:format) devise_token_auth/passwords#new edit_api_v1_user_password GET /api/v1/auth/password/edit(.:format) devise_token_auth/passwords#edit api_v1_user_password PATCH /api/v1/auth/password(.:format) devise_token_auth/passwords#update PUT /api/v1/auth/password(.:format) devise_token_auth/passwords#update POST /api/v1/auth/password(.:format) devise_token_auth/passwords#create cancel_api_v1_user_registration GET /api/v1/auth/cancel(.:format) api/v1/auth/registrations#cancel new_api_v1_user_registration GET /api/v1/auth/sign_up(.:format) api/v1/auth/registrations#new edit_api_v1_user_registration GET /api/v1/auth/edit(.:format) api/v1/auth/registrations#edit api_v1_user_registration PATCH /api/v1/auth(.:format) api/v1/auth/registrations#update PUT /api/v1/auth(.:format) api/v1/auth/registrations#update DELETE /api/v1/auth(.:format) api/v1/auth/registrations#destroy POST /api/v1/auth(.:format) api/v1/auth/registrations#create api_v1_auth_validate_token GET /api/v1/auth/validate_token(.:format) devise_token_auth/token_validations#validate_token api_v1_auth_failure GET /api/v1/auth/failure(.:format) api/v1/auth/omniauth_callbacks#omniauth_failure GET /api/v1/auth/:provider/callback(.:format) api/v1/auth/omniauth_callbacks#omniauth_success GET|POST /api/v1/auth/omniauth/:provider/callback(.:format) api/v1/auth/omniauth_callbacks#redirect_callbacks api_v1_auth_omniauth_failure GET|POST /api/v1/auth/omniauth/failure(.:format) api/v1/auth/omniauth_callbacks#omniauth_failure GET /api/v1/auth/:provider(.:format) redirect(301) api_v1_users GET /api/v1/users(.:format) api/v1/users#index api_v1_user GET /api/v1/users/:id(.:format) api/v1/users#show
  10. (C) Diverseas inc. Devise token Authͷத਎Λͪΐͬͱ͚ͩ঺հ 23 Deviseʹґଘ͍ͯͯ͠APIαʔόʔߏங͍ͨ͠ਓΉ͚ͷGem mount_devise_token_auth_forϝιουͰίϯτϩʔϥ΁ͷϧʔςΟϯά΋ॊ ೈʹ

    namespace :api do namespace :v1 do mount_devise_token_auth_for "User", at: "auth", controllers: { registrations: "api/v1/auth/registrations", sessions: "api/v1/auth/sessions", omniauth_callbacks: "api/v1/auth/omniauth_callbacks" } resources :users, only: %i(index show) end en
  11. (C) Diverseas inc. Devise token Authͷத਎Λͪΐͬͱ͚ͩ঺հ 24 def create @resource

    = resource_class.new(sign_up_params.except(:confirm_success_url)) @resource.provider = provider …………৭ʑͳॲཧ begin # override email confirmation, must be sent manually from ctrl resource_class.set_callback("create", :after, :send_on_create_confirmation_instructions) resource_class.skip_callback("create", :after, :send_on_create_confirmation_instructions) if @resource.respond_to? :skip_confirmation_notification! # Fix duplicate e-mails by disabling Devise confirmation e-mail @resource.skip_confirmation_notification! end if @resource.save yield @resource if block_given? unless @resource.confirmed? # user will require email authentication @resource.send_confirmation_instructions({ client_config: params[:config_name], redirect_url: @redirect_url }) else # email auth has been bypassed, authenticate user @client_id = SecureRandom.urlsafe_base64(nil, false) @token = SecureRandom.urlsafe_base64(nil, false) @resource.tokens[@client_id] = { token: BCrypt::Password.create(@token), expiry: (Time.now + @resource.token_lifespan).to_i } @resource.save! update_auth_header end render_create_success else clean_up_passwords @resource render_create_error end rescue ActiveRecord::RecordNotUnique clean_up_passwords @resource render_create_error_email_already_exists end
  12. (C) Diverseas inc. Devise token Authͷத਎Λͪΐͬͱ͚ͩ঺հ 25 ͜Μͳײ͡ͰDviseTokenAuth͕ఏڙ͍ͯ͠ΔίϯτϩʔϥΛΦʔόϥΠυͯ͠͠ ͔΋த਎ͷॲཧ͚ͩಠࣗͷϩδοΫΛॻ͘Έ͍ͨͳ͜ͱ΋ class

    Api::V1::Auth::RegistrationsController < DeviseTokenAuth::RegistrationsController before_action :authenticate_user!, except: :create def create super do |resource| #RedisʹtokenಥͬࠐΉΑ͏ͳॲཧͱ͔ͱ͔ End end end
  13. (C) Diverseas inc. BCrypt devise಺Ͱར༻͞Ε͍ͯΔ҉߸ํࣜ͸Blowfishͱ͍͏҉߸ԽํࣜΛϓϩάϥϜͰ ར༻Ͱ͖ΔΑ͏ʹͨ͠Bcryptͱ͍͏҉߸ ฏจύεϫʔυɹ=> BCrypt => $2a$10$Vrye.IAv2dXM/WN8tnX84.YzHqnKj7HnMfnvK5nxB/l8ZPfaAdHH6

    $2a: version $10$: hashΛॻ͚Δճ਺costͱݺ͹ΕΔ Vrye.IAv2dXM/WN8tnX84.ɿϋογϡΛ͔͚Δͱ͖ʹར༻͞ΕΔϥϯμϜͳ஋Ͱsaltͱݺ͹ΕΔ YzHqnKj7HnMfnvK5nxB/l8ZPfaAdHH6ɿϋογϡԽ͞Εͨύεϫʔυ 27
  14. (C) Diverseas inc. BCrypt • Blowfish҉߸ʹग़ͯ͘Δϫʔυ͸Salt&Pepper͕ͩΧϨʔͷํ͕Θ͔Γ΍͍͢ ฏจύεϫʔυɿࡐྉ $2a: ؁ޱɺਏޱɺதਏʁ $10$:

    ΧϨʔϧʔΛ͍ͭ͘ೖΕΔʁ Vrye.IAv2dXM/WN8tnX84.ɿδϟϫΧϨʔΛ͔ͭ͏ͷ͔ʁίΫϚϩΛ࢖͏ͷ͔ʁ͸ͨ·ͨ… YzHqnKj7HnMfnvK5nxB/l8ZPfaAdHH6ɿΧϨʔͷຯ ๻͸͜͜·ͰΛϨγϐͱݺͿɻɹ-> $2a$10$Vrye.IAv2dXM/WN8tnX84. 28
  15. (C) Diverseas inc. BCrypt Ϩγϐͷੜ੒ [12] pry(main)> BCrypt::Engine.generate_salt(10) => "$2a$10$DoFj6s85Ore1Z4/xDt0hyu"

    ͲΜͳϨγϐΛ࢖͏͔͸ਓͦΕͧΕ [15] pry(main)> BCrypt::Engine.hash_secret('password', "$2a$10$DoFj6s85Ore1Z4/xDt0hyu") => "$2a$10$DoFj6s85Ore1Z4/xDt0hyuPToxollA2u4IsXCDo/e.qBNyNYxTXEa" [1] pry(main)> BCrypt::Engine.generate_salt(10) => "$2a$10$XcIZ8V8vmJlf3b9QtdHFAO" [2] pry(main)> BCrypt::Engine.hash_secret('password', "$2a$10$XcIZ8V8vmJlf3b9QtdHFAO") => "$2a$10$XcIZ8V8vmJlf3b9QtdHFAO26yvKx0N5Ftac5WI6DatvcCkE93Adaq" 29
  16. (C) Diverseas inc. BCrypt Ϩγϐͷੜ੒ [12] pry(main)> BCrypt::Engine.generate_salt(10) => "$2a$10$DoFj6s85Ore1Z4/xDt0hyu"

    ࡐྉΛม͑ͯ΋ग़ͯ͘ΔΧϨʔ͸มΘΓ·͢ [15] pry(main)> BCrypt::Engine.hash_secret('password', "$2a$10$DoFj6s85Ore1Z4/xDt0hyu") => "$2a$10$DoFj6s85Ore1Z4/xDt0hyuPToxollA2u4IsXCDo/e.qBNyNYxTXEa" [18] pry(main)> BCrypt::Engine.hash_secret('PASSWORD', "$2a$10$DoFj6s85Ore1Z4/xDt0hyu") => "$2a$10$DoFj6s85Ore1Z4/xDt0hyuRBKkpQdV8Pv7dWNrzo1LH3TzPBMFLhO" 30
  17. (C) Diverseas inc. BCrypt • deviseͷதͰ͸…. def self.compare(klass, hashed_password, password)

    return false if hashed_password.blank? bcrypt = ::BCrypt::Password.new(hashed_password) if klass.pepper.present? password = "#{password}#{klass.pepper}" end password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt) Devise.secure_compare(password, hashed_password) end • ݁࿦͸ΩονϯʢDBʣ͕มΘͬͯ΋Ϩγϐͱࡐྉ͕͋Ε͹ಉ͡ΧϨʔ͸࡞ΕΔ 31
  18. (C) Diverseas inc. ࿩͸͜͜ͰऴΘΒͳ͍ • ͱ͋Δ೔… ωਃke͞Μ͕དྷͯ… ʮ࠷ۙௐࢠͲ͏Ͱ͔͢ʙʁʯ • ๻ʮҠߦΛͲ͏͠Α͏͔৭ʑߟ͑ͳ͖Ό͍͚ͳͯ͘..

    ΞϨίϨ͋Ε͜Ε….ʯ • ωਃke͞ΜʮҠߦ͚ͨ͠ͲϢʔβσʔλΛϢʔβࣗ਎ʹ௚ͯ͠΋Β͏ඞཁ͕ ͋Γͦ͏ͳΒྑ͍ମݧ͕ఏڙͰ͖ͳ͍ͱ͍͏ҙຯͰ΋ɺ࠷ॳ͔Βొ࿥ͯ͠΋ Β͏ͷ΋͍͍͔΋͠Εͳ͍Ͱ͢Ͷɹɿʣʯ • Ko-kun ʮʂʂͦΕ͕Ұ൪͍͍ʂʂʯ • ๻ʮ!?ʯ 32
  19. (C) Diverseas inc. ࿩͸͜͜ͰऴΘΒͳ͍ • ͱ͋Δ೔… ωਃke͞Μ͕དྷͯ… ʮ࠷ۙௐࢠͲ͏Ͱ͔͢ʙʁʯ • ๻ʮೝূपΓύεϫʔυೝূͱ͔FacebookϩάΠϯͱ͔

    ΞϨίϨ͋Ε͜ Ε….ʯ • ωਃke͞Μʮ࠷ۙ͏ͪͷ৽͍͠αʔϏεͰ͸Firebaseʹೝূͯ͠΋Βͬͯ Ϣʔβͷηογϣϯ؅ཧΛ͢ΔτʔΫϯ͚ͩࣗલ؅ཧͯ͠·͢Αɻɹ FirebaseΛ࢖͑͹޾ͤʹͳΕΔ͔΋͠Ε·ͤΜͶɿʣʯ • ๻ ʮʂʂͦΕ͕Ұ൪͍͍ʂʂʯ • ko-kunʮ!?ʯ 34