LoginSignup
1
1

More than 3 years have passed since last update.

[Kotlin]ホワイトリストに特定のpathを含む文字列がある場合の対応

Posted at

ホワイトリストにURLのhost部分だけじゃなく、pathも含めたい時の対処方法です。

前提条件

URLを開く際、以下のようなことをするAndroidアプリがあると仮定します。

  • ↓の処理でホワイトリストとuriのhost部分を比較し、ホワイトリストに登録されている文字列がuriに含まれていたらアプリ内のWebViewで、含まれてなければ外部ブラウザで開く
WhiteListRepository.kt
fun compareWhiteList(uri: Uri): Boolean {
    return uri.host in whiteList
}
  • ホワイトリストはサーバー上で管理しており、アプリ起動時にFetchしてくる(上記のwhiteListに格納)
  • ホワイトリストは以下の文字列が登録されている
hogehoge.com
hugahuga.co.jp

突然の仕様変更

ある日、「ホワイトリストにpiyopoyo.com/system/menuを追加したい」という要望が上から降ってきました。
現在の実装では、host部分しかホワイトリストと比較していません。さてどうしましょうか…

間違い例

まず初めに、uriにpathを含むホワイトリスト文字列があるかを判定すれば良いのでは?と考え、以下のような処理を追加しました。

WhiteListRepository.kt
fun compareWhiteList(uri: Uri): Boolean {
    // path含むホワイトリストの判定
    val whiteListWithPathList = whiteList.filter { it.contains("/") } // pathを含むホワイトリストだけ抽出
    if (whiteListWithPathList.any { "$uri".contains(it) }) return true // uriに文字列が含まれてればtrueをreturn

    // path含むホワイトリストの判定がfalseならば、従来通りhost部分のみを比較
    return uri.host in whiteList 
}

一見OKなように見えますが、1点問題があります。
これだと、https://google.com?q=piyopoyo.com/system/menuのようなuriでもWebViewで開いてしまいます。
ホワイトリスト処理として期待される正しい動きではありません。

(※補足)
わざわざwhiteListWithPathListで抽出してるのは、whiteListで比較するとhttps://xxx/hogehoge.comのようなuriも該当してしまうためです。

正解例

「host + path」は前方一致で判定しなくてはなりません。
よって正しくは↓

WhiteListRepository.kt
fun compareWhiteList(uri: Uri): Boolean {
    return whiteList.any { "$uri".startsWith("https://$it") } // uriの先頭がhttps://{ホワイトリストの文字列}で始まっているかの判定をreturn
    // return uri.host in whiteList ← 上の処理でhostとの比較をまかなえるので削除できる
}

終わり

host + pathのホワイトリストの判定は、前方一致しなければいけないことに気をつけましょう。

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