Edited at

【Go言語/PHP】「ログインしていないと見れない画像」を実装

More than 1 year has passed since last update.

条件は「ログインしていないと」に限らず、「夜しか見れない」とかでもなんでもよく、ある条件のときだけ閲覧できる仕組みです。


仕組み


  • 画像ファイル本体はWebからアクセスできないディレクトリに置く。

  • ログインチェックし、ログインしていないなら403を返す。

  • ログインしているなら対応する画像データを(レスポンスヘッダでContent-typeを指定したうえで)返す。

  • ログインしていても、対応する画像がなければ404を返す。

という感じです。


Goで実装

ginというWAFを使ってリクエストとレスポンスを制御していますが、そこは重要ではないので好きに置き換えて大丈夫です。


main.go

package main

import (
"github.com/gin-gonic/gin"
"os"
"mime"
"strings"
"io/ioutil"
)

func main() {
router := gin.Default()
router.GET("/img/:filename", getImage)
router.Run(":8080")
}

// ログインしているときだけ画像を表示
func getImage(c *gin.Context) {
if isLoggedin() {
// ログインしている
dir := "./img"
filename := c.Param("filename")
file, e := os.Open(dir+"/"+filename)
if e == nil {
// 画像が存在する
contentType := getContentType(filename)
fileData, _ := ioutil.ReadAll(file)
c.Data(200, contentType, fileData)
} else {
// 画像が存在しない
c.Status(404)
}
} else {
// ログインしていない
c.Status(403)
}
}

// ファイル名からcontentTypeを取得
func getContentType(filename string) string {
pos := strings.LastIndex(filename, ".")
contentType := mime.TypeByExtension(filename[pos:])
return contentType
}

// ログインしているかどうか
func isLoggedin() bool {
return true // ログインしている
// return false // ログインしていない
}


画像は以下のように配置しておく。

project/

├ main.go
└ img
└ hoge.png


確認

実行後、http://localhost:8080/img/hoge.pngにアクセスして画像が表示されることを確認してください。

次に、isLoggedin()の結果をfalseに変更した上でもう一度アクセスし、403エラーが返ってくることを確認してください。

実際のファイルの閲覧権限を弄ったりしているわけではないので、./img/ディレクトリがウェブから見える位置にあれば当然見えてしまうので注意してください。


PHP版


index.php

<?php 

define('DIR', '../img/');

function main() {
if(isLoggedin()) {
// ログインしている
$filePath = DIR.basename($_GET['filename']);
if(file_exists($filePath)) {
// 画像が存在する
$contentType = mime_content_type($filePath);
header('Content-Type: Content-type: '.$contentType);
readfile($filePath);
} else {
// 画像が存在しない
header('HTTP/1.1 404 Not Found');
}
} else {
// ログインしていない
header('HTTP/1.1 403 Forbidden');
}
}

function isLoggedin() {
return true; // ログインしている
// return false; // ログインしていない
}

main();


画像は以下のようにドキュメントルートの外に配置しておく。

project/

├ htdocs
│ └ index.php
└ img
└ hoge.png


確認

http://xxx/index.php?filename=hoge.pngへアクセスし、Goのときと同様にisLoggedin()がtrueのときだけ見れることを確認して下さい。

ルーティングはhtaccessなりで変更し、http://xxx/img/hoge.pngで実行できるようにしたらいいかと思います。