들어가면서... |
안녕하세요. Bucket Place개발자 Cloud Travel입니다. 오랜만에 형식에 맞춰서 글을 쓰는 느낌이 듭니다. Rails에 적응하고, 분석하고, 예제를 실험해보는 과정에서 필요한 내용을 간략하게 메모만 해왔는데, Session에 대해서는 잘 알고 넘어가야 하는 것 같아서 형식에 맞춰 잘 정리하려고 합니다.
어떤 프레임워크 또는 언어를 사용하더라도 Session관리는 웹 어플리케이션을 제작하고 관리하는데 큰 이슈가 됩니다. 이에 대해서 정확히 알고 사용할 필요가 있습니다. 일단, 오늘의 목표는 다음과 같습니다.
- Session에 관련된 컨트롤러 생성
- Session에 필요한 각 모듈을 제작
- Session의 정보를 Database와 사용자의 브라우져에 저장
- 이와 동시에 사용자 로그인과 로그아웃 기능을 제작
또한, 이 페이지는 이전에 사용자에 관련된 Database가 완성되있다는 가정하에 진행이 됩니다.
Session controller 뼈대 생성 및 뷰 설정 |
일단, 세션에 관련된 정보를 관리할 Session controller를 생성합니다.
$ rails generate controller Sessions
...
세션 정보를 RESTFul Architecture에 맞게 설정을 하기 위해서 routes.rb 에 resource를 등록해줍니다.
$ vi config/routes.rb
... resources :users resources :sessions, only: [:new, :create, :destroy] root 'static_pages#home' match '/signup', to: 'users#new', via: 'get' match '/signin', to: 'sessions#new', via: 'get' match '/signout', to: 'sessions#destroy', via: 'delete' ...
resources :sessions, only: [:new, :create, :destroy]
: Sessions을 RESTful 아키텍쳐를 이용하는데 이중에서 new, create 그리고 destroy Method만을 이용한다는 것입니다.
match '/signin', to: 'session#new', via:'get'
: /session/new 페이지로 들어가는 url을 /signin으로 변경을 합니다.
match '/signin', to: 'session#destroy', via:'delete'
다음으로는 컨트롤러와 뷰를 제작해주면 됩니다. 위에서 new, create, destroy 메소드만을 사용한다고 했기 때문에 controller의 기본틀은 다음과 같이 됩니다.
$ vi app/controllers/sessions_controller.rb
class SessionsController < ApplicationController def new end def create end def destroy end end
회원 로그인을 위한 view를 생성해줍니다.
$ vi app/views/sessions/new.html.erb
<h1>Sign in</h1> <div class="row"> <div class="span6 offset3"> <%= form_for(:session, url: sessions_path) do |f| %> <%= f.label :email %> <%= f.text_field :email %> <%= f.label :password %> <%= f.password_field :password %> <%= f.submit "Sign in", class: "btn btn-large btn-primary" %> <% end %> <p>New user? <%= link_to "Sign up now!", signup_path %></p> </div> </div>
Session 정보 저장하기 |
세션을 사용하기 위해서는 몇가적인 추가적 설정 및 User 테이블을 변경하여 세션 정보를 저장할 필요가 있다.
일단, 세션은 어플리케이션 전체에서 사용되기 때문에 application_controller에 session helper를 포함시켜준다.
$ vi app/controllers/application_controller.rb
class ApplicationController < ActionController::Base protect_from_forgery with: :exception include SessionsHelper end
다음으로는 사용자 테이블을 아래의 그림과 같이 변경해야 한다. remember_token은 세션 정보를 저장할 특성이다.
새로운 특성 추가를 위해서는 다음과 같은 행동을 해주면된다. 이미 여러번 해봤을 꺼라고 생각한다.
$ rails generate migration add_remember_token_to_users
...
$ vi db/migrate/[Time_stamp]_add_remember_token_to_users.rb
class AddRememberTokenToUsers < ActiveRecord::Migration def change add_column :users, :remember_token, :string add_index :users, :remember_token end end
변경된 내용을 추가시키기 위해서 migration을 실행해준다.
$ bundle exec rake db:migrate
이제는 사용자의 세션 토큰을 생성하고 암호화하는 코드를 작성해야 한다. 이 정보들은 사용자 모델과 밀접하기 때문에 사용자 컨트롤러에서 설정을 해준다.
$ vi app/models/user.rb
class User < ActiveRecord::Base before_save { self.email = email.downcase } before_create :create_remember_token . . . def User.new_remember_token SecureRandom.urlsafe_base64 end def User.encrypt(token) Digest::SHA1.hexdigest(token.to_s) end private def create_remember_token self.remember_token = User.encrypt(User.new_remember_token) end end
사용자 정보를 새로 저장할 때(즉, 회원가입할 경우) 저장하기 전에 세션 토큰을 생성하고 저장하는 부분을 만들어준 것이다.
- before_create :create_remember_token : create 함수를 실행전에 create_remember_token함수를 실행
- new_remember_token : 64bit 길이의 키를 랜덤하게 생성한다.
- encrypt : 키를 암호화 한다.
- create_remember_token : remember_token 변수를 설정하여 토큰 정보를 저장한다.
로그인 & 로그 아웃 |
로그인에 관련된 컨트롤러와 모듈을 제작해보자.
일단, 로그인을 하게 되면 사용자가 정확한 정보를 입력했는지를 판단하고(비밀번호 확인), 결과를 알려준다. 성공을 했다면, sign_in 함수를 호출하고 사용자 정보를 보여주는 페이지로 이동을 시키고, 그 외에는 에러메세지를 flash를 이용하여 보여준다.
$ vi app/controllers/sessions_controller.rb
class SessionsController < ApplicationController . . . def create user = User.find_by(email: params[:session][:email].downcase) if user && user.authenticate(params[:session][:password]) sign_in user redirect_to user else flash.now[:error] = 'Invalid email/password combination' render 'new' end end def destroy sign_out redirect_to root_url end end
폼으로 받아들인 email이 존재하는지의 여부와 비밀번호로 생성된 인증코드와 일치여부를 판단한다. 다음으로는 세션에 관련된 부가적인 기능을 추가하도록 하자.
$ vi app/helpers/sessions_helper.rb
module SessionsHelper # 로그인시 세션 토큰을 만들고 쿠키에 저장 def sign_in(user) remember_token = User.new_remember_token cookies.permanent[:remember_token] = remember_token user.update_attribute(:remember_token, User.encrypt(remember_token)) self.current_user = user end # 로그인했는지 여부를 확인 def signed_in? !current_user.nil? end # 이후의 페이지에서 세션토큰을 위해서 사용자 정보를 가져온다. def current_user=(user) @current_user = user end # 쿠키에 저장된 토큰을 가져와서 사용한다. 이 토큰을 이용해서 사용자 정보도 가져온다. def current_user remember_token = User.encrypt(cookies[:remember_token]) @current_user ||= User.find_by(remember_token: remember_token) end # 로그 아웃 def sign_out self.current_user = nil cookies.delete(:remember_token) end end
각각의 모듈은 다음과 같다.
- sign_in(user) : 회원 로그인시 세션 토큰을 생성하고 쿠키에 저장을 한다.
- signed_in? : 뷰에서 회원 로그인 여부를 이용해서 뷰를 관리하기 위해서 존재한다.
- current_user=(user) : 로그인한 회원의 정보를 가져온다.
- current_user : 쿠키에 저장된 정보를 이용하여 다른 페이지를 컨트롤 한다.
- signe_out : 로그아웃
마무리 |
흠.. 먼가 간략하게 적으려다 보니 부족한 내용이 있을지도 모른다.
이렇게 부분으로 설명하기 힘들다. Rails는... 그래서 왠만한 책들이 하나의 프로젝트를 다루는 것일지도 모르겠다...