Go言語のwebフレームワーク「martini」アプリにBasic認証をかける
martini-contribにauthパッケージが用意されているのでそれを使う。
Basic認証をかける機能しかない。
$ go get github.com/codegangsta/martini-contrib/auth
使い方
package main import ( "github.com/codegangsta/martini" "github.com/codegangsta/martini-contrib/auth" ) func main() { m := martini.Classic() // basic auth m.Use(auth.Basic("username", "password")) m.Get("/", func() string { return "Hello, world" }) m.Run() }
ソースを読んでいて気がついたこと。
認証文字列が一致するかどうかは単純に==で比較するのではなく、cryptoパッケージのsubtle.ConstantTimeCompareを使っている。
これによって文字列比較にかかる時間からuser/passを推測できないようにしている。
文字列の長さが異なる場合は一致するはずがないけど、同じ理由でわざわざ文字列比較をしてからfalseを返している。
package auth import ( "crypto/subtle" ) // SecureCompare performs a constant time compare of two strings to limit timing attacks. func SecureCompare(given string, actual string) bool { if subtle.ConstantTimeEq(int32(len(given)), int32(len(actual))) == 1 { return subtle.ConstantTimeCompare([]byte(given), []byte(actual)) == 1 } else { /* Securely compare actual to itself to keep constant time, but always return false */ return subtle.ConstantTimeCompare([]byte(actual), []byte(actual)) == 1 && false } }