1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

手軽にできる!RailsとNext.jsでURL上のIDを暗号化する方法

Posted at

はじめに

Rails APIとNext.jsで開発しているときにURL上でIDを平文のまま載せたくない場合の対策になります。

実現させたいこと

具体的には、Rails APIをバックエンドに、Next.jsをフロントエンドとして利用し、
ユーザーがブラウザ上でproduct/1などといったIDを直接露出する形ではなく、暗号化したIDを使ったURL(例: product/暗号化されたID)を用いて、データへのアクセスを行います。

やること

Rails API側

やることとしては共通鍵を設定し、暗号/復号化時にそれを参照するようにしています。

app/controllers/application_controller.rb
class ApplicationController < ActionController::API
  before_action :set_encryptor

  private

# 共通鍵生成関数
  def set_encryptor
    # Rails.application.credentials.saltには32文字の適当な英数字を設定
    secret_key = Rails.application.credentials.salt
    # secret_keyを使用して暗号/復号化のための共通鍵を作成
    @encryptor = ActiveSupport::MessageEncryptor.new(secret_key[0, 32])
  end

# 暗号化用関数
  def encrypt(data)
    encrypted_data = @encryptor.encrypt_and_sign(data)
    Base64.urlsafe_encode64(encrypted_data)
  end

# 復号化用関数
  def decrypt(data)
    decoded_encrypted_data = Base64.urlsafe_decode64(data)
    @encryptor.decrypt_and_verify(decoded_encrypted_data)
  end
end

Next.js側

フロント側はもらったものを表示するのみのため実装例は不要と思いますが記載します。

pages/product/[encryptedId].js
import axios from 'axios';
import { useRouter } from 'next/router';
import { useState, useEffect } from 'react';

function ProductPage() {
  const { encryptedId } = useRouter().query;
  const [product, setProduct] = useState({});
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    if (!encryptedId) return;
    axios.get(`/api/products/${encryptedId}`)
      .then(response => {
        setProduct(response.data);
        setLoading(false);
      })
      .catch(error => {
        setError(error);
        setLoading(false);
      });
  }, [encryptedId]);

  if (loading) return <div>Loading...</div>;
  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      <p>${product.price}</p>
    </div>
  );
}

export default ProductPage;

最後に

今回はRailsとNext.jsでActiveSupport::MessageEncryptorを使用する方法を紹介しましたが、
別のアプローチはたくさんあるのでケースによって検討いただければと思います。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?