👌

画像を扱うサービスを作るときは位置情報を消そう

2023/09/19に公開

この記事はなに?

なにかしらのサービスを作ったとき、とくに画像を扱うサービスで第三者に画像が見える場合は、位置情報をちゃんと削除しようねというお話です。状況によりますね。

どのようなときに位置情報を消す?

逆にどのようなときに位置情報を残しても良いでしょうか?

  • ユーザが明確に位置情報の利用の意思を示したとき
  • サービスが位置情報の利用を前提としているとき

くらいではないでしょうか?
これ以外の場合にもあるかもしれませんが、基本的には許可されていない場合を除いて位置情報を削除するべきだと思います。
特に、わたしがリリースしているぺったんというアプリでは、家で飼っているペットがターゲットになっていて画像のダウンロードもできるので、確実に削除するべきです。家バレするので。

そもそもクライアントとサーバどちらで消す?

正直なところ、これに関しては好みの問題なのかなと思っています。

例えばサーバ側で消してあげれば、クライアント側では何も考えずに画像を送ってあげれば良いことになります。ただ、位置情報を消すかどうかを制御するならパラメータでわたしてあげないといけないですね。
一方でクライアント側で消すなら、サーバ側は何も考えずにもらったものを保存すれば良いことになりますが、例えばiOSとAndroidのクライアントを(それぞれネイティブで)用意するのであればそれぞれ実装してあげる必要がありますね。

実装例

ここでは、サーバサイドのKotlinでの実装例を示したいと思います。ちなみに、使っているライブラリはJava製です。こんなとき、Null Safeを保証しづらいの、もにょりますね。

使うのは org.apache.commons:commons-imaging:1.0-alpha3です。
JPEGのByteArrayがあったとして、

RemoveGpsData.kt
fun ByteArray.removeLocationMetadata(): ByteArray {
    val metaData = Imaging.getMetadata(this) ?: return this
    return (metaData as? JpegImageMetadata)?.let { jpegImageMetadata ->
        jpegImageMetadata.exif?.outputSet?.apply {
            gpsDirectory?.fields?.forEach { gpsTag ->
                removeField(gpsTag.tag)
            }
            findField(ExifTagConstants.EXIF_TAG_GPSINFO)?.let {
                removeField(ExifTagConstants.EXIF_TAG_GPSINFO)
            }
        }.run {
            ByteArrayOutputStream().use { baos ->
                BufferedOutputStream(baos).use { bos ->
                    ExifRewriter().updateExifMetadataLossless(this@removeLocationMetadata, bos, this)
                }
                baos.toByteArray()
            }
        }
    } ?: kotlin.run {
        this
    }
}

のように実装したものを通してあげれば位置情報が削除できているはずです。

Discussion