Masteries

技術的なことや仕事に関することを書いていきます.

Go言語でMixed Contentsをなるべく発見する

ウェブサービス/ウェブサイトのHTTPS化にあたっては, Mixed Contentsへの対応が求められます. 既にHTTPSを有効にする作業が完了している状態で, Mixed Contentsが発生していないかを確認したいのであれば, (Node.js製のツールですが)Mixed Contentsの発見のために mcdetect などを使うことができるでしょう.

www.npmjs.com

例えば, このブログ(https://papix.hatenablog.com/)を mcdetect でチェックすると, 次のような結果になります:

$ mcdetect https://papix.hatenablog.com/
Checking https://papix.hatenablog.com/ ...

Targets checked: 1
Errors (blockable content): 0
Warnings (optionally blockable content): 0

ここでの Errors (blockable content)Warnings (optionally blockable content) は, どちらもHTTPSのページでHTTPのコンテンツを読み込んでいる状態ですが, 前者はそのコンテンツがHTTPのみで配信されている状態, 後者はそのコンテンツがHTTPとHTTPSの両方で配信されている状態(= コンテンツを読み込むときのURLを, http://... から https://... にすればMixed Contentsが解決できる)を指します.

mcdetect の課題

mcdetect は, 実際にHeadless Chromeを利用してMixed Contentsの検出を行います. そのため, Mixed Contentsを検索する対象ページは, (前述の通り)HTTPS化が有効になっている必要があります. 実際, mcdetect にHTTPのURLを与えると, Mixed Contentsを見つけるために, 自動的にHTTPSのURLとしてアクセスを行い, Mixed Contentsの検出を行います:

$ mcdetect http://example.com/
Checking https://example.com/ ...

Targets checked: 1
Errors (blockable content): 0
Warnings (optionally blockable content): 0

そのため, 実際にHTTPS化を有効にする前に, なるべくMixed Contentsを見つけたい! という用途には利用できません.

Go言語でMixed Contentsをなるべく発見する

※ "なるべく"とあるように, 以下のコードで全てのMixed Contentsが発見出来るわけではありません. あくまでMixed Contentsを見るける上での参考情報としてお使い下さい.

そこで, Go言語でMixed Contentsを"なるべく"見つけるコードを書きました:

package main

import (
    "fmt"
    "log"
    "regexp"
    "strings"

    "github.com/PuerkitoBio/goquery"
)

func main() {
    doc, err := goquery.NewDocument("https://papix.hatenablog.com/")
    if err != nil {
        log.Fatal(err)
    }

    for _, tag := range []string{"img", "audio", "video", "script", "iframe"} {
        doc.Find(tag).Each(func(i int, s *goquery.Selection) {
            src, _ := s.Attr("src")
            if strings.HasPrefix(src, "http://") {
                fmt.Printf("error\t%s\t%s\n", tag, src)
            }
        })
    }

    doc.Find("link").Each(func(i int, s *goquery.Selection) {
        rel, _ := s.Attr("rel")
        if strings.HasPrefix(rel, "stylesheet") {
            href, _ := s.Attr("href")
            if strings.HasPrefix(href, "http://") {
                fmt.Printf("error\tlink\t%s\n", href)
            }
        }
    })
}

前述の通り, "なるべく"なので100%のMixed Contentsを見つけられる訳ではないですが, これである程度のMixed Contentsを見つけることができます. ここでは,

  • img, audio, video, script, iframeタグのsrcにHTTPのURLがないか
  • linkタグで, かつrelstylesheetのときに, hrefにHTTPのURLがないか

を見ています. 加えて目視で,

  • style タグの中でHTTPのコンテンツを呼び出していないか
  • scriptタグで呼び出しているJavaScriptや, linkタグで呼び出しているスタイルシートでHTTPのコンテンツを呼び出していないか

...辺りを確認しておくと, 更に良さそうです.

まとめ

Go言語のgithub.com/PuerkitoBio/goqueryを使って, なるべくMixed Contentsを見つけるコードを紹介しました.

前述の通り, 実際にHTTPS化した後にMixed Contentsの対応を出来るのであれば, mcdetect を利用する方が確実ではありますが, そうもいかない場合はこういうったスクリプトである程度Mixed Contentsを潰した後, HTTPS化を実施して, mcdetectで最終チェックをする, という手が有効になるかもしれません.