最近GoでCORSを用いてフロントエンド/バックエンド間の通信を実現するケースが多いので、CORSのコード構成について掘り下げてみます。
CORSのcredentialとは?
CORS(Cross-Origin Resource Sharing)は、ブラウザ上で動作するWebアプリケーションで、異なるオリジン(ドメイン、プロトコル、ポート)の間でデータのやり取りを行うための仕組みです。
CORSのcredentialとは、Cookieや認証トークンなどのクレデンシャル情報を含むリクエストを送信することを許可するための属性です。デフォルトではCORSリクエストでCookieは送信されませんし、BASIC認証は送れません。Credential情報を含むリクエストの送信をするためには、それを許可するオプションをバックエンドでもフロントエンドでも作る必要があります。
credential属性をtrueに設定することで、クレデンシャル情報を含むリクエストを送信することができます。ただし、credential属性をtrueに設定すると、セキュリティ上のリスクが増大するため、注意が必要です。credential属性を使用する場合は、適切な設定と認証を実装する必要があります。また、リクエストを送信する側と受信する側の両方で、credential属性をtrueに設定する必要があります。CORSのcredentialは、バックエンドでもフロントエンドでも指定します。
バックエンドでは以下のように書く。
func (app *application) CORS(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "https://x-digger.com")
if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Credentials", "true") }
フロントエンドでは以下のように書く。
let requestOptions: RequestInit = {
body: JSON.stringify(requestBody),
method: method,
headers: headers,
credentials: "include",}
一般的にCORSでセキュリティを高める方法
1.オリジン制限を設定する
オリジン制限は、特定のオリジンからのみリクエストを受け入れるようにサーバーを構成することを意味します。これにより、悪意のあるユーザーが悪意のあるコードを実行するために、クロスサイトスクリプティング攻撃を使用して別のオリジンからのリクエストを送信することを防ぐことができます。
2.プリフライトリクエストを要求する
プリフライトリクエストは、実際のリクエストを送信する前に、ブラウザがサーバーに対して事前に確認するリクエストです。これにより、クロスサイトスクリプティング攻撃を防止することができます。
3.認証情報を使用する
CORSを使用する場合、認証情報を含めることができます。これにより、サーバーは、クロスドメインリクエストが許可されるかどうかを判断する前に、認証情報を確認できます。これにより、悪意のあるユーザーが認証情報を使用してリクエストを送信することを防止することができます。
4.適切なHTTPメソッドを使用する
CORSを使用する場合、適切なHTTPメソッド(GET、POST、PUT、DELETEなど)を使用することが重要です。GETリクエストは情報を取得するだけであり、POSTリクエストは情報を送信するために使用されます。PUTリクエストは情報を更新するために使用され、DELETEリクエストは情報を削除するために使用されます。これらのメソッドを正しく使用することにより、サーバーに対する攻撃を防止することができます。
5.HTTPSを使用する
HTTPSを使用することで、通信中に情報を暗号化することができます。これにより、通信が傍受されても情報が盗まれることがなくなります。HTTPSを使用することは、セキュリティを高めるための重要な手段です。
プリフライトリクエストを要求する場合のサンプルコード
func main() {
// CORSの設定
cors := func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
cors
関数の中で、リクエストメソッドがOPTIONS
の場合に、Access-Control-Allow-Methods
ヘッダーとAccess-Control-Allow-Headers
ヘッダーを設定して、ステータスコード200
を返しています。これにより、ブラウザはサーバーに対してプリフライトリクエストを送信することができます。
オリジン制限を設定する場合のサンプルコード
example.com
のオリジンからのリクエストを許可し、それ以外のオリジンからのリクエストは拒否します。cors
関数の中で、Origin
ヘッダーを取得し、example.com
以外のオリジンからのリクエストにはAccess-Control-Allow-Origin
ヘッダーを設定しないようにしています。また、http.HandleFunc
によって、ルートパスに対するハンドラーを設定しています。http.ListenAndServe
によって、サーバーを起動しています。ListenAndServe
関数の第二引数に、CORSの設定を行ったcors
関数を渡しています。
func main() {
cors := func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
origin := r.Header.Get("Origin")
if origin == "https://example.com" {
w.Header().Set("Access-Control-Allow-Origin", origin)
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
}
if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})}
CORSでセキュリティを高めるためには?
- Access-Control-Allow-Originヘッダーの値をより厳密に設定する
Access-Control-Allow-Originヘッダーの値にhttps://x-digger.comが設定されているが、これはすべてのオリジンからのリクエストを許可している。より厳密に設定する場合、特定のドメインからのリクエストのみを許可するように設定することが推奨される。 - Access-Control-Allow-Headersヘッダーの値をより制限的に設定する
Access-Control-Allow-HeadersヘッダーにAccept、Content-Typeが設定されているが、これに加えて、認証トークンなどの重要な情報を含むヘッダーも送信される場合は、それらのヘッダーも明示的に許可する必要がある。より制限的に設定する場合は、必要最小限のヘッダーのみを許可するように設定することが推奨される。 - OPTIONSメソッドに対するレスポンスをより制限的に設定する
OPTIONSメソッドに対するレスポンスに、必要なAccess-Control-Allow-*ヘッダーを設定している。しかし、OPTIONSメソッドは実際にはリソースの取得や更新などの処理を行わないため、不要な情報を含むレスポンスを返すことはセキュリティ上のリスクとなる。より制限的に設定する場合は、必要最小限の情報のみを含むレスポンスを返すように設定することが推奨される。
コメント