0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Session

Sessionとは、ユーザーごとの状態をサーバー側で保持する仕組みです。Webは本来「ステートレス」(通信が終わると状態を保持しない)なプロトコルであるため、ユーザーがログイン中かどうかなどの情報を保持するためにSessionが使われます。

Sessionの仕組み

  1. ユーザーがログインすると、サーバー側でSessionを生成し、SessionIDを発行します
  2. SessionIDはCookieやURLパラメータを通じてクライアントに渡されます
  3. 次回以降のリクエストで、SessionIDが送信されることで、サーバー側でユーザーを識別できます

Sessionの特徴

  • サーバー側にデータを保存
    • Sessionデータはサーバー上に保持されます(例: メモリやデータベース)
  • クライアントの負担が少ない
    • クライアント側ではSessionIDだけを保持
  • セキュリティが高い
    • Sessionデータはサーバー側に保存されるため、直接改ざんされにくい

Sessionの欠点

  • サーバーのリソースを消費する
  • ロードバランサーを使用する場合、Session管理が複雑になる(Sessionの共有が必要)

Cookie

Cookieは、Webブラウザにデータを保存する仕組みです。ユーザー識別や状態管理のために使われ、SessionIDをクライアントに渡す手段としても活用されます。

Cookieの仕組み

  1. サーバーがクライアントにレスポンスを返す際に、HTTPヘッダーにCookieを付与します
  2. クライアント(ブラウザ)はCookieを保存します
  3. 次回以降のリクエストで、保存したCookieをHTTPヘッダーに含めてサーバーに送信します

Cookieの特徴

  • クライアント側にデータを保存
    • 状態や設定情報をブラウザに保持します
  • 簡単に使用可能
    • HTTPリクエストとレスポンスに付加するだけで利用できます

Cookieの用途

  • SessionIDの保存
  • ユーザー設定(テーマ、言語など)の保持
  • トラッキング情報(広告や分析ツールで利用)

Cookieの制限

  • 保存容量はブラウザごとに制限されている(通常4KB程度)
  • 改ざんや盗聴のリスクがあるため、暗号化やセキュアな通信(HTTPS)が推奨されます

SessionとCookieの違い

項目 Session Cookie
データの保存場所 サーバー側 クライアント側
データ量の制限 サーバーのリソースに依存 通常4KB程度
セキュリティ 比較的高い(サーバー管理) 改ざんや盗聴のリスクがある
有効期限 通常ブラウザを閉じると終了 有効期限を設定可能
使用例 ログイン情報、ショッピングカート ユーザー設定、SessionIDの保存

Goサンプルコード

package main

import (
	"fmt"
	"net/http"

	"github.com/gorilla/sessions"
)

// セッションストアの設定(Cookieストアを使用)
var store = sessions.NewCookieStore([]byte("your-secret-key"))

func loginHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
		return
	}

	// フォームデータからユーザー名を取得
	username := r.FormValue("username")
	if username == "" {
		http.Error(w, "Username is required", http.StatusBadRequest)
		return
	}

	// セッションを取得(新規作成含む)
	session, _ := store.Get(r, "session-name")

	// セッションにユーザー情報を保存
	session.Values["username"] = username
	session.Save(r, w) // セッションを保存

	fmt.Fprintf(w, "Logged in as %s", username)
}

func profileHandler(w http.ResponseWriter, r *http.Request) {
	// セッションを取得
	session, _ := store.Get(r, "session-name")

	// セッションからユーザー名を取得
	username, ok := session.Values["username"].(string)
	if !ok || username == "" {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	fmt.Fprintf(w, "Welcome, %s!", username)
}

func logoutHandler(w http.ResponseWriter, r *http.Request) {
	// セッションを取得
	session, _ := store.Get(r, "session-name")

	// セッションデータをクリア
	session.Options.MaxAge = -1 // クッキーの有効期限を無効にする
	session.Save(r, w)          // セッションを保存

	fmt.Fprintln(w, "Logged out")
}

func main() {
	http.HandleFunc("/login", loginHandler)
	http.HandleFunc("/profile", profileHandler)
	http.HandleFunc("/logout", logoutHandler)

	fmt.Println("Server started at :8080")
	http.ListenAndServe(":8080", nil)
}

/loginにPOST

Logged in as hogehoge

/profileにGET

Welcome, hogehoge!

/logoutにGET

Logged out

SessionとCookieのセキュリティ対策

HTTPSを使用する

  • 暗号化された通信を利用し、SessionIDやCookieが盗聴されるリスクを軽減します

SessionIDの保護

  • Sessionハイジャックを防ぐため、SessionIDは予測困難なものにする
  • 定期的にSessionIDを更新(Session固定攻撃の防止)

CookieのHttpOnly属性

  • JavaScriptからアクセスできないようにすることで、XSS攻撃から保護します

CookieのSecure属性

  • HTTPS通信時のみCookieを送信

CSRFトークンの活用

  • Sessionを利用するリクエストにはCSRFトークンを含める
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?