俺の User Agent がそんなに万能なわけがない
はじめに USerAgent(UA) とは?
UserAgentとは HTTP Request に含まれるデータです。Header 等に含まれます。
例えば、以下の感じでそれを開いているブラウザ―の種類が分かります。
上が Google Chrome、下が Microsoft Edge での結果です。
お試し用の HTML が以下です。
<html>
<body>
<script>
document.write(window.navigator.userAgent);
</script>
</body>
</html>
え、ナニコレめっちゃ便利じゃん!
...なんてことはありません。結論からいうとこの UserAgent、結構ガバガバです。
何がいけない?
お手軽に偽装できる
この UserAgent は結構簡単に編集、もとい偽装できちゃいます。
実例を含めて確認しましょう。シンプルなサンプルを用意しました。
上の html もおいてます。
必要なもの
- git
- npm
- VSCode
- VSCode の REST Client のExtension
以下の index.js を実行します。
const restify = require('restify');
// Create HTTP server
const server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, () => {
server.use(restify.plugins.bodyParser({ mapParams: true }));
console.log("Sever is running")
});
// Listen for incoming requests.
server.get('/', (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write("UserAgent:"+req.headers['user-agent']);
console.dir(req.headers)
res.end();
});
簡単に実行方法を。以下で npm module 等の準備を(node-server Directory で実行)
(init の方は不要かもです。)
npm init
npm install restify
module が入ったら以下でプログラムを実行。
node index.js
この状態で、ua-test.http を開きます。先の Extension が入ってたら、以下みたいに Send Request ができるはず。
試に上側のリクエストを押してみます。
上側の Send Request を実行した結果が以下です。
UserAgent:vscode-restclient
VSCode が実行してるよって言ってますね。
続いて、下側の Send Request を実行した結果が以下です。
UserAgent:"hogehoge"
hogehoge してますね。
と、こんな風にリクエストを送信する側が任意で編集できてしまうわけですね。
(ちなみに実際の実行イメージは以下の感じ)
でもそれって JavaScript とかのコードの話ですよね?
いいえ、違います。リクエスト全般です。ブラウザ―での表示もいうなれば HTTP リクエストです。
つまり、「いつからブラウザ―では大丈夫だと錯覚していた?」となるわけです。
先の HTML を Microsoft Edge で開いてみます。Chorome 等、Chromium をベースとしてるブラウザ―であれば、恐らく開発者ツールのネットワーク状態という機能から、UserAgent を編集できます。
通常通り開いてみた。
開発者ツールから UA をいじれた。
はい、御覧のように Edge で開いているのに Chrome のようにできました。
(そして何なら Windows を Android と偽装することでもできちゃいます。)
何がまずいん?
大部分の人には影響ないと思います。ただ、こういった UA を使用してブラウザ―や OS に依存した実装をしているサイトに関してはちょっと面白くない事態ですよね。
例えば、OS やブラウザ―の種類によって表示を変えているとか、ブラウザ―によって実行できる JavaScript とかを判定してる人とかはちょっとアレかもです。
また、その辺の話であればかわいいもんですが、一番やばいのは、セキュリティ的な判定ロジックとかに UA を使用してる人ですかね。いや、そんな使い方してる人がいるのかは存じませんが。
じゃあ、どうしたらよいん?
そもそも使う必要があるのかを検討
今後そもそもそういった UA の仕組みが必要なことがどのくらいあるのかは疑問ですが、
使わないに越したことはないと思います。(そもそもスマホでしか使わせたくない、PC でしか使わせたくないみたいな場面があるのであれば、それぞれに特化させたネイティブ アプリにするのもありかも?)
機能として使用可能かを判定
今後、モダンなブラウザ―ではあまり考慮する必要もないかもですが、
もしも使いたい機能を使いたいという場合には、機能の検出を使うのが良いと言われます。
オライリーの JavaScript パターンという本でも UserAgent は最後の手段で、
機能の検出等で代用しようと言われています。(UserAgent は基本アンチパターンと言っています)
例えば、attachment を使いたい場合には、以下のようなことが考えられます。
if(document.attachment){}
if(typeof document.attachment)
ご参考程度に。
結論
UserAgent って便利は便利だけど、簡単に編集できちゃいます。
正直、UserAgent を必要とする場面が今後どのくらいあるのかは分かりませんが、
もし使うとしたら他の道がないのか、かつ偽装された時にどういう影響がでるのかは
十分に検討した上で使うのが良いと思います。
ちなみに回避策なんかはもっといいのが色々あるのかもしれない。
その道が長い方々がそういう知見を持ってたら聞いてみたいところ。
余談
実体験
あまり大きな声では言えないのですが、一度私生活で UA を変更することで
サイトの動作が変わることを確認しちゃったことがあります。
あるサイトを開いたら「ご利用の端末では利用いただけません」って表示されたので、
出来心で「ははぁん!さてはお前、UA 使ってるなぁ?」って思って開発者ツールを
開いてみたら案の定な感じでした。
抽選を行うサイトだったのですが、スマホでサイトを開いて、ログインして、諸々の情報を入力する手間を惜しみ、そのまま申し込んでしまいました。
あ、ちなみに結果としては抽選は外れてました。
JavaScript パターンについて
余談ですが、上述の書籍は 2011 年に出版されています。なので、「IE のバージョンの違いなんかで使用できる機能に差があるよ」みたいな話もあります。また、 promise のような機能等はまだ紹介されていません。
そういった、今は当たり前な機能の話がなかったり、今後 IE デスクトップ アプリのサポートが終了した後には、ブラウザ―が Web 標準に沿って考える必要もなくなることになるかと思いますが、そういった歴史的な楽しみ方もありかもです。(私は数年前に BookOff で安かったから何も考えずに買ってただけで、そんな深い意図等はないですが)
(IE デスクトップアプリ EoS については以下の公式 Windows Blog を。)
スマホ対応したレスポンシブデザインについて
CSS 完全にどころか全く理解していなくて恐縮ですが、個人的にスマホにも対応した Web デザインって話をきくと、@media みたいな css 内の表記で対応してることが多いような印象を受けてます。
この辺は UA には依存してなさそうにも感じてますが、ちょっと自分で試せてないので何とも言えない感じがします。
Discussion