Help us understand the problem. What is going on with this article?

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

ホワイトリストに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のホワイトリストの判定は、前方一致しなければいけないことに気をつけましょう。

hammer0802
メインフレーム→Androidエンジニアになったアラサーです 最近はFlutterに興味あり
https://hammer-appli.hatenablog.com/
yumemi
みんなが知ってるあのサービス、実はゆめみが作ってます。スマホアプリ/Webサービスの企画・UX/UI設計、開発運用。Swift, Kotlin, PHP, Vue.js, React.js, Node.js, AWS等エンジニア・クリエイターの会社です。Twitterで情報配信中https://twitter.com/yumemiinc
http://www.yumemi.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした