Belajar Ruby - Encoding, Validasi Input & Data Handling Aman
Series/Belajar Ruby/Episode 16
Episode 16 of 23

Belajar Ruby - Encoding, Validasi Input & Data Handling Aman

Episode ini membahas penanganan data yang aman: encoding UTF-8 dan transkoding string untuk mencegah encoding errors, validasi dan sanitasi input, strong params di Rails, hashing password dengan bcrypt, serta prinsip least privilege.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Episode 15 menutup celah umum dengan tools keamanan. Episode 16 ini melangkah lebih dalam: menangani data dengan benar sejak masuk sampai disimpan. Dua tema besar dibahas — encoding string dan validasi input — plus hashing password serta prinsip least privilege.

Encoding yang salah adalah sumber error aneh seperti ArgumentError: invalid byte sequence in UTF-8 yang sering muncul di aplikasi multi-bahasa. Validasi input mencegah data cacat masuk ke database. Hashing password memastikan data sensitif tetap aman bila database bocor.

Encoding String di Ruby

Memahami String#encoding

Setiap string di Ruby membawa informasi encoding. Metode String#encoding mengembalikan labelnya, dan String#valid_encoding? mengecek apakah byte yang terkandung sesuai dengan label tersebut:

RubyMengecek encoding string
teks = "halo"
puts teks.encoding
puts teks.valid_encoding?

puts teks.encoding menampilkan encoding default file source. Ketika membaca file eksternal atau response HTTP, jangan asumsikan UTF-8 — selalu cek dan sesuaikan encoding-nya.

Transkoding dan Pencegahan Error

Untuk mengubah byte dari satu encoding ke encoding lain, gunakan String#encode. Bila byte tidak valid, encode melempar exception, jadi tangkap dengan rescue atau paksa penggantian karakter:

RubyTranskoding dengan penggantian
latin = teks.encode("ISO-8859-1")
puts latin.encoding
 
teks.encode("UTF-8", invalid: :replace, undef: :replace)

teks.encode("ISO-8859-1") menghasilkan string baru dalam encoding Latin-1. Opsi invalid: :replace mengganti byte yang tidak dikenal dengan karakter pengganti alih-alih melempar error. Untuk input web, pastikan meta charset dan header Content-Type menyatakan UTF-8 secara konsisten.

Validasi dan Sanitasi Input

Validasi Input

Validasi menjawab pertanyaan: apakah data ini bentuknya benar? Di model ActiveRecord, validasi dinyatakan deklaratif:

RubyValidasi model ActiveRecord
class Pengguna < ApplicationRecord
  validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
  validates :usia, numericality: { only_integer: true, greater_than: 0 }
end

validates :email, presence: true memastikan email ada, dan format disesuaikan dengan pola email standar. numericality memastikan usia angka positif. Validasi di model adalah garis pertahanan pertama; tambahkan validasi di sisi client hanya untuk pengalaman pengguna, bukan keamanan.

Strong Params di Rails

Masih ada celah: parameter mass assignment. Penyerang bisa mengirim field tersembunyi seperti admin: true. Rails menutupnya dengan strong params — whitelist field yang boleh di-assign:

RubyStrong params di Rails
def params_pengguna
  params.require(:pengguna).permit(:email, :nama, :usia)
end

params.require(:pengguna).permit(:email, :nama, :usia) hanya mengizinkan tiga field tersebut masuk ke model. Field lain, termasuk admin atau role, diabaikan. Prinsip ini berlaku juga untuk parameter query di aplikasi non-Rails: ambil eksplisit setiap field yang kalian butuhkan.

Hashing Password dengan bcrypt

Menyimpan password mentah adalah pelanggaran terbesar. Simpan hanya hash-nya menggunakan bcrypt — algoritma yang lambat secara sengaja untuk memperlambat brute force. Rails sudah menyertakan bcrypt melalui has_secure_password; untuk project lain tambahkan gem:

Menambahkan bcrypt
gem install bcrypt
bundle add bcrypt

bundle add bcrypt menambahkan gem ke Gemfile dan meng-install-nya. Di kode, hash password saat registrasi dan verifikasi saat login:

RubyHash dan verifikasi password
require "bcrypt"
hash = BCrypt::Password.create("rahasia123")
puts BCrypt::Password.new(hash) == "rahasia123"

BCrypt::Password.create("rahasia123") menghasilkan hash dengan salt acak otomatis. Verifikasi dilakukan dengan membandingkan ulang, bukan dengan mendekripsi — bcrypt satu arah. Jangan pernah menulis log yang berisi password atau token.

Prinsip Least Privilege

Least privilege berarti memberikan akses seminimal mungkin yang dibutuhkan untuk bekerja. Di database, buat akun aplikasi yang tidak punya hak DROP atau TRUNCATE. Di kode, jangan berikan kemampuan penuh kepada input pengguna, dan selalu verifikasi otorisasi sebelum operasi sensitif:

RubyOtorisasi sebelum aksi
def hapus_tugas(id)
  tugas = Tugas.find_by(id: id, pemilik_id: current_user.id)
  raise "Tidak berhak" unless tugas
  tugas.destroy
end

tugas.destroy hanya berjalan ketika pemilik cocok dengan pengguna yang sedang login. Pola scoping seperti ini mencegah IDOR, insecure direct object reference. Terapkan least privilege juga pada secrets, IAM, dan service account.

Tip

Audit rutin: cek daftar grant database, key environment yang tidak terpakai, dan user yang sudah nonaktif. Privilege yang mengendap adalah risiko yang tidak terpantau.

Penutup

Inti yang harus dibawa pulang:

  • String#encoding dan valid_encoding? adalah gerbang pertama menangani teks.
  • String#encode dengan opsi penggantian mencegah crash pada byte tak valid.
  • Validasi model dan strong params memfilter data sebelum masuk database.
  • bcrypt menyimpan password sebagai hash satu arah dengan salt otomatis.
  • Least privilege membatasi akses akun, database, dan secrets seminimal mungkin.
  • Selalu verifikasi otorisasi pemilik sebelum operasi sensitif.

Di episode 17 kita berpindah dari keamanan ke performa: mengaktifkan YJIT dengan --yjit, mengukur waktu dengan Benchmark, memakai ruby-prof untuk menemukan hotspot, serta memahami GC.stat dan GC.config. Aplikasi yang aman kini akan kita buat cepat juga.

Belajar Ruby - Encoding, Validasi Input & Data Handling Aman | Belajar Ruby