Seongsiks

Being A DevOpser. Powered by
Obtvse, highlight.js, theme toc Creative Commons License
Seongsiks Twitter Github Email
DevOps Ruby On Rails Chef Projects Misc Movies & Drama ME

Rails4-4 Strong Parameters, Authenticity Token, Filters, Sessions, Flash

Overview

이번 포스트는 attr_accesibles같은 파라미터 엑세서 변경, filters, 세션 보안강화, 커스텀 플래시에 대한 이야기입니다.

Strong parameters

<form action="/users" method="post">
  <p>
    <input id="name" name="name" type="name" />
  </p>
  <p>
    <input name="commit" type="submit" value="Save"  />
    
    <input name="admin" type="hidden" value="1"  />
    
  </p>
</form>

만약 핵커가 다음과 같이 input을 추가 한다음, submit 을 때리면 어떻게 될까요? 만약 admin 필드가 boolean타입으로 되어 있었다면 admin권한을 가진 사용자 하나가 추가되면서... ㅠ.ㅠ. 이런것을 방지하기위해 whitelisting이라고 하는데 기존에 Rails3에서는 이 작업의 책임이 Model에서 했었죠? 다음 코드에서 보시것과 같이요.

# File name : models/user.rb
class User < ActiveRecord::Base
  attr_accessible :name
end

#File name : controllers/users_controller.rb
def update
  if @user.update_attributes(params[:user])
    redirect_to @user, notice: 'Updated'
  else
    render action: 'edit'
  end
end

이렇게 하면 attr_accessible로 선언된 필드를 제외한 필드에 대해서 업데이트나 인서트를 하려고 하면 모델에서 이를 ActiveMode::MassAssignmentsSecurity::Error를 발생시키면서 이를 막아줍니다.

그러나 Rails4에서 이 whitelisting parameter기능이 모델에서 컨트롤러로 넘어왔습니다.

이제 모델에서는 아무것도 하지 않고 컨트롤러에서 다음과 같이 적어주면 됩니다.

# File name : controllers/user_controller.rb
def update
  # attr_accessiable :name과 동일
  user_params = params.require(:user).permit(:name)
  if @user.update_attributes(user_params)
    redirect_to @user, notice: 'Updated'
  else
    render action: 'edit'
  end
end

이렇게 하면 사용자가 admin이라는 파라미터를 날려도 #permit메소드가 알아서 이를 지워버리고 name이라는 필드만 넘겨주게 됩니다.

#permit메소드는 디폴트로 파라미터의 타입도 같이 체크 해주는데요. 다음이 허용되는 파라미터 타입들입니다.

  • String
  • Symbol
  • NilClass
  • Numeric
  • TrueClass, FalseClass
  • Date, Time, DateTime
  • StringIO, IO
  • ActionDispatch::Http::UploadFile, Rack::Test::UploadFile

디폴트 이렇게 걸러진 파리미터들은 다 로깅이 되는데요. 로깅되는것 뿐만 아니라 exception까지 발생 시키고 싶으시다면,

# File name :  config/application.rb
config.action_controller.action_on_unpermitted_parameters = :raise

이렇게 설정해 주시면 됩니다.

Rails4에서 계속해서 attr_accessible을 사용하고 싶으시다면 protected_attributes젬을 이용하세요

Rails4로 업그레이드하지 않고 Strong Parameters을 사용하려고 하시거나, 좀 더 자세한 기능을 확인하고 싶으신 분은 [여기 클릭]

Authenticity Token

Rails에서는 기본적으로 모든 폼에 Authenticity_token이라는 히든 필드가 추가 됩니다.(form helper을 사용했을경우)

 <form id='edit_user_1' . . .>
  <input name="authenticity_token" type="hidden" value="y2GIknkh...=" />
   ....
 </form>

그래서 확인되지 않은 인증 토큰이 오면 세션을 지워버리고 세션을 리셋해버리고 경고를 로깅합니다.

WARNING: Can't verify CSRF token  authenticity

Rails4에서는 이 동작에 대해서 좀 더 커스터 마이징할 수 있는 기능이 추가 됐습니다.

# File name : controllers/applcation.rb
# 인증되지 않은 토큰이 오면 exception발생 default
protect_from_forgery with: :exception 
# 인증되지 않은 토큰이 오면 세션을 비워버림
protect_from_forgery with: :null_session
# 인증되지 않은 토큰이 오면 이전 세션을 지워버리고 새 새션 만들기
protect_from_forgery with: :reset_session

Filters/Actions

기존에 컨트롤러에서 before_filter많이 쓰셨죠. 그런데 생각해보니.. 이건 실제로 아무것도 filtering하고 있지 않다는 것을 깨닫고 새로운 이름을 주었답니다. action이라고요. 그래서 이제 Rails4에서는 Filter라고 쓸 수 도 있지만, Action이라고 하셔도 됩니다.

Cookie Based Session Store

Rails에서는 세션 정보를 로컬에 있는 쿠키에 저장합니다.

rails cookie

이 값은 사용자가 수정하지는 못하지만, 읽을 수 있었습니다. 그리고 루비를 이용해 이 값을 까 볼 수 조차 있죠.

require 'rack'
cookie = 'daf1b24...'
Rack::Session::Cookie::Base64::Marshal.new.decode(cookie)
=> {"session_id"=> "adfadf98ad8fea8dfa908d7", "user_id"=>"123", "_csrf_token_"=>"2adsfliji231212plfaRE" }

Rails4에서는 여기서 암호화하는 기능을 추가 해서 위 코드와 같이 decode를 해도 nil만 리턴 됩니다. Rails4에서는 key를 기준으로 이를 암호화 하게 됩니다. 이 키는 다음과 같이 설정됩니다.

# File name : config/initializers/secret_token.rb
MyApp::Application.config.secret_key_base = '123123123123'

그런데 이 상태로 Github같은데 올리면 공개되어 버리겠죠? 그럴때는 되도록

MyApp::Application.config.secret_key_base = ENV['SECRET_KEY_BASE']

이런 식으로 환경 변수로 숨겨 두시는게 좋겠죠?

Flash

Flash는 컨트롤러에서 값을 주면 view로 넘어가서 사용자에게 메시지를 전달할 때 사용하죠.

# File name : controllers/users_controller.rb
if @item.save
  flash[:notice] = "User Saved"
  redirect_to @item
end

이제 뷰에서

# File name : views/items/show.html.erb
<p id="notice"><%= flash[:notice] %></p>

실제 html에서는

# HTML
<p id="notice">Item_created </p>

그리고, 뷰에서 간편하게

<%= notice %>
<%= alert %>

이렇게도 사용가능합니다. 그런데 이건 이미 등록된 flash type에 대해서만 이런 키워드를 사용할 수 있었습니다. 이제 Rails4에서는 이런 Flash Type을 새로 정의 해서 사용할 수 있게 되었습니다. 사용법도 간단합니다. 컨트롤러 상단에 add_flash_types 키워드를 이용해서 선언해 주면 기존 notice나 alert처럼 자유롭게 쓸 수 있습니다.^^

# File name : controllers/application_controller.rb
class ApplicationController < ActionController::Base
  add_flash_types :new_type, :nice
end

이번 포스트는 Rails4로 바뀌면서 강화된 전반적인 보안 강화에 관한 이야기였네요. 그럼 다음 포스트에서는 Rails4에서 강화된 View에 대해서 알아 보겠습니다.


[이전 Rails4-3 ActiveModel]
[다음 Rails4-5 View]
comments powered by Disqus
Back to Ruby On Rails