Update Japanese translation

Rewrote to easy to read expression.
Fixed misspelled words.
Omitted too-much commas.
This commit is contained in:
Hirofumi Tamori
2015-01-03 17:21:24 +09:00
parent c3a3576a3b
commit 7309afca46
7 changed files with 31 additions and 30 deletions

View File

@@ -1,6 +1,6 @@
# 4 フォーム
フォームは我々が普段Webアプリケーションを書く時によく使ツールです。フォームを通して便利にユーザにサーバとデータをやり取りさせることができます。以前にWeb開発をしたことのあるユーザにとってはフォームはとてもお馴染みのものです。しかしC/C++のプログラマからすると少々ばかり門外漢かもしれません。フォームとは一体何でしょうか?
フォームは普段Webアプリケーションを書く時によく使われるツールです。フォームを通して便利にユーザにサーバとデータをやり取りさせることができます。以前にWeb開発をしたことのあるユーザにとってはフォームはとてもお馴染みのものです。しかしC/C++のプログラマからすると少々取っ付きにくいかもしれません。フォームとは一体何でしょうか?
フォームは表の要素を含むエリアです。フォームの要素はユーザがフォームの中で(例えば、テキストフィールド、コンボボックス、チェックボックス、セレクトボックス等です。)情報を入力する要素です。フォームはフォームタグ(\<form\>)で定義します。
@@ -10,11 +10,11 @@
...
</form>
Goではformの処理にすでにとても簡単な方法が用意されています。Requestの中にformを専門に処理するものがあります。とても簡単にWeb開発に利用できるものです。4.1節の中でGoがどのようにフォームの入力を処理するかご説明します。いかなるユーザの入力も信用はできないので、これらの入力に対しバリデーションを行う必要があります。4.2節ではどのように普通のバリデーションを行うか、細かいデモンストレーションを行います。
Goではformの処理に簡単な方法が既に用意されています。Requestの中にformを専門に処理するものがあり簡単にWeb開発に利用できるす。4.1節の中でGoがどのようにフォームの入力を処理するかご説明します。いかなるユーザの入力も信用はできないので、これらの入力に対し検証を行う必要があります。4.2節では一般的にどのように検証を行うか、細かいデモンストレーションを行います。
HTTPプロトコルはステートレスなプロトコルです。ではどのようにして一人のユーザを同定するのでしょうかまた、フォームが複数回送信されてしまわないように保証するにはどうするのでしょうか4.3と4.4節ではcookie(cookieはクライアントに保存される情報です。handlerとサーバを通る度にやり取りされるデータです。)等をより詳しくご紹介します。
HTTPプロトコルはステートレスなプロトコルです。ではどのようにして一人のユーザを同定するのでしょうかまた、フォームが複数回送信されてしまわないように保証するにはどうするのでしょうか4.3と4.4節ではcookie(cookieはクライアントに保存される情報です。HTTP Headerを通してサーバーとやり取りされます)等をより詳しくご紹介します。
フォームにはもうひとつファイルをアップロードできるという大きな機能があります。Goはファイルのアップロードをどのように処理しているのでしょうか大きなファイルをアップロードする際効率よく処理するにはどうすればよいでしょうか4.5節ではGoによるファイルのアップロード処理の知識を一緒に勉強します。
フォームにはもうひとつファイルをアップロードできるという大きな機能があります。Goはファイルのアップロードをどのように処理しているのでしょうか大きなファイルをアップロードする際効率よく処理するにはどうすればよいでしょうか4.5節ではGoによるファイルのアップロード処理の知識を一緒に勉強します。
## 目次
![](images/navi4.png?raw=true)

View File

@@ -1,6 +1,6 @@
# 4.1 フォームの入力を処理する
まずフォームによる送信の例を見てみましょう。以下のようなフォームの内容があるとします。login.gtplというファイルを新規作成します。新しくディレクトリを作ってその中に入れてください
まずフォームによる送信の例を見てみましょう。以下のようなフォームのコンテンツがあるとします。login.gtplというファイルを新規作成します。新しくディレクトリを作ってその中に入れてください
<html>
<head>
@@ -15,9 +15,9 @@
</body>
</html>
上で送信されるフォームはサーバの`/login`に渡ます。ユーザが情報を入力しログインをクリックした後、サーバのルーティングの`login`にリダイレクトします。まずはこの送信が何のメソッドによるものか判断する必要があります。POSTでしょうかGETでしょうか
上で送信されるフォームはサーバの`/login`に渡されます。ユーザが情報を入力しログインをクリックした後、サーバのルーティングの`login`にリダイレクトします。まずはこの送信が何のメソッドによるものか判断する必要があります。POSTでしょうかGETでしょうか
httpパッケージではとても簡単な方法で取得することができます。前のwebの例を基礎にloginページのformデータをどのように処理するか見てみましょう。
httpパッケージにはそれを取得するとても簡単な方法があります。前のwebの例を基礎にloginページのformデータをどのように処理するか見てみましょう。
package main
@@ -66,7 +66,7 @@ httpパッケージではとても簡単な方法で取得することができ
}
上のコードにおいてリクエストを取得するメソッド`r.Method`を通じて完了することがわかります。これは文字列型の変数です。GET, POST, PUT等のmethod情報を返します。
上のコードにおいてリクエストのメソッドを取得する`r.Method`だけで済むことがわかります。これは文字列型の変数です。GET, POST, PUT等のmethod情報を返します。
login関数では`r.Method`に従ってログイン画面を表示するのかログインロジックを処理するのかが判断されます。GETメソッドによるリクエストの場合はログイン画面を表示し、その他のメソッドによるリクエストではログインロジックを処理します。例えばデータベースを検索したり、ログイン情報を検証したりといった事です。
@@ -76,7 +76,7 @@ login関数では`r.Method`に従ってログイン画面を表示するのか
図4.1 ユーザログイン画面
我々がユーザ名とパスワードを入力してもサーバは何も出力しません。なぜでしょうか?デフォルトではHandlerの中ではformの内容を自動的に解析しないからです。必ず明示的に`r.ParseForm()`をコールした後でなければ、このフォームのデータに対して操作を行うことはできません。コードを少し修正して、`fmt.Println("username:", r.Form["username"])`の前に`r.ParseForm()`という一行を追加してください。再コンパイルしてもう一度入力、送信してみると、今度はサーバがあなたの入力したユーザ名とパスワードを出力するはずです。
我々がユーザ名とパスワードを入力してもサーバは何も出力しません。なぜでしょうかデフォルトではHandlerの中ではformの内容を自動的に解析しないからです。必ず明示的に`r.ParseForm()`をコールした後でなければ、このフォームのデータに対して操作を行うことはできません。コードを少し修正して、`fmt.Println("username:", r.Form["username"])`の前に`r.ParseForm()`という一行を追加してください。再コンパイルしてもう一度入力、送信してみると、今度はサーバがあなたの入力したユーザ名とパスワードを出力するはずです。
`r.Form`では全てのリクエストのデータが含まれています。例えばURLの中のquery-string、POSTのデータ、PUTのデータなどです。URLのquery-stringフィールドとPOSTが衝突する場合はsliceに保存されます。これには複数の値が保存されています。Goのオフィシャルドキュメントでは次のバージョンでPOST、GETといったデータは分離されると述べています。

View File

@@ -1,20 +1,20 @@
# 4.2 フォームに入力された内容の検証
Web開発の原則はユーザが入力したいかなる情報も信用してはならないということです。そのためユーザの入力した情報を検証しフィルターすることは非常に重要になってきます。ブログやニュースの中でどこそこのホームページがハッキングされたりセキュリティホールが存在するといったことをよく聞くかもしれません。これらの大部分はユーザの入力した情報に対してホームページが厳格な検証を行わなかった事によるものです。そのため、安全なWebプログラムを書くために、フォームの入力を検証する意義は非常に大きいのです。
Web開発はユーザが入力したいかなる情報も信用してはならないという原則があります。そのためユーザの入力した情報を検証しフィルターすることは非常に重要になってきます。ブログやニュースの中でどこそこのホームページがハッキングされたりセキュリティホールが存在するといったことをよく聞くかもしれません。これらの大部分はユーザの入力した情報に対してホームページが厳格な検証を行わなかった事によるものです。そのため、安全なWebプログラムを書くために、フォームの入力を検証する意義は非常に大きいのです。
Webアプリケーションを書く時は主につの方面のデータ検証があります。ひとつはページ上でのjsによる検証で現在この方面では多くのプラグインがあります。例えばValidationJSプラグインなどがそうです、もうひとつはサーバ側での検証です。この節ではどのようにサーバでの検証を行うか解説します。
Webアプリケーションを書く時は主につの場所でデータ検証を行います。ひとつはページ上でのJavaScriptによる検証で現在この方面では多くのプラグインがあります。例えばValidationJSプラグインなどがそうです、もうひとつはサーバ側での検証です。この節ではどのようにサーバでの検証を行うか解説します。
## 必須フィールド
あるフォーム要素から一つの値を取り出したいとします。例えば前の節のユーザ名はどのように処理するのでしょうかGoにはbuiltin関数`len`があり、文字列の長さを得ることができます。lenを使ってデータの長さを測ることができます。例えば
あるフォーム要素から一つの値を取り出したいとします。例えば前の節のユーザ名はどのように処理するのでしょうかGoにはbuiltin関数`len`があり、文字列の長さを得ることができます。lenを使ってデータの長さを測ることができます。例えば
if len(r.Form["username"][0])==0{
//空だった場合の処理
}
`r.Form`は異なる型のフォーム要素の空白に対して異なる処理を行います。空のテキストフィールド、テキストエリアおよびファイルアップロードに対して、その要素の値を空にします。また選択されていないコンボボックスやセレクトボックスr.Formの中にはそもそもその項目を作りません。上の例の中の方法でデータを取得した時プログラムはエラーを発生させます。そのため、`r.Form.Get()`を使って値を取る必要があります。なぜなら、もしフィールドが存在しなかった場合、この方法で取得すると空の値を得るからです。ですが、`r.Form.Get()`は単体の値しか得ることができません。もしmapの値であれば、かならず上の方法で得る必要があります。
`r.Form`は異なる型のフォーム要素の空白に対して異なる処理を行います。空のテキストフィールド、テキストエリアおよびファイルアップロードに対して、その要素の値を空にします。また選択されていないコンボボックスやセレクトボックスr.Formの中にはそもそもその項目を作りません。上の例の中の方法でデータを取得した時プログラムはエラーを発生させます。そのため、`r.Form.Get()`を使って値を取る必要があります。なぜなら、もしフィールドが存在しなかった場合、この方法で取得すると空の値を得るからです。ですが、`r.Form.Get()`は単体の値しか得ることができません。もしmapの値であればず上の方法で得る必要があります。
## 数
たとえばフォームからある人の年齢が50歳や10歳といった具体的な値を必要としていて、"おっさん"とか"若者"というようなものでなかったとします。このようにフォームの入力フィールドの中で数字のみを許容するようにさせたい場合、整数かどうかを判断するために、まずint型に変換を行ってから処理を行います。
えばフォームからある人の年齢が50歳や10歳といった具体的な値を必要としていて、"おっさん"とか"まだ若い"というようなものでなかったとします。このようにフォームの入力フィールドの中で数字のみを許容するようにさせたい場合、整数かどうかを判断するために、まずint型に変換を行ってから処理を行います。
正の整数を判断しようとする場合は、まずint型に変換してから処理を行います
@@ -34,7 +34,7 @@ Webアプリケーションを書く時は主につの方面のデータ検
return false
}
性能の高さを必要とするユーザからすればこれはよく話題にのぼる問題です。彼らはなるべく正規表現を避けるべきだと考えています。なぜなら正規表現の速度は一般的に遅いからです。しかし現在のようにコンピュータの性能がこれほど発達した時代では、このように簡単な正規表現の効率と型変換関数の間ではそれほど大きな差はありません。もしあなたが正規表現に詳しく、他の言語でも使用されているのであれば、Goの中で正規表現を使うのは便利な方法の一つです。
性能の高さを必要とするユーザからすればこれはよく話題にのぼる問題です。彼らはなるべく正規表現を避けるべきだと考えています。なぜなら正規表現の速度は一般的に遅いからです。しかし現在のようにコンピュータの性能がこれほど発達した時代では、このように簡単な正規表現の効率と型変換関数の間ではそれほど大きな差はありません。もしあなたが正規表現に詳しく、他の言語でも使用されているのであれば、Goの中で正規表現を使うのは便利な方法の一つです。
>Goの正規表現の実装は[RE2](http://code.google.com/p/re2/wiki/Syntax)です。すべての文字はUTF-8エンコーディングです。
@@ -95,7 +95,7 @@ selectには以下の要素があるとします
return false
## ラジオボタン
男と女という性別の選択肢を出力するようなラジオボタンでどれかが選択されているか判断するとします。15歳の退屈な少年がhttpプロトコルの本を片手にtelnetクライアントからあなたのプログラムに対してリクエストを送信したとしましょう。あなたは男に1を、女に2を設定していて、彼が3という値を送信した場合、あなたのプログラムは例外を出すでしょうかプルダウンメニューの判断と同じように我々が得ようとしている値がそもそも設定されたものであるかを判断しなければなりません。
男と女という性別の選択肢を出力するようなラジオボタンでどれかが選択されているか判断するとします。15歳の退屈な少年がhttpプロトコルの本を片手にtelnetクライアントからあなたのプログラムに対してリクエストを送信したとしましょう。あなたは男に1を、女に2を設定していて、彼が3という値を送信した場合、あなたのプログラムは例外を出すでしょうかプルダウンメニューの判断と同じように我々が得ようとしている値がそもそも設定されたものであるかを判断しなければなりません。
<input type="radio" name="gender" value="1">男
<input type="radio" name="gender" value="2">女
@@ -131,8 +131,7 @@ selectには以下の要素があるとします
上の`Slice_diff`という関数には私のオープンソースのライブラリが含まれますsliceとmapを操作するライブラリ[https://github.com/astaxie/beeku](https://github.com/astaxie/beeku)
## 日付と時間
ユーザが入力した日時が有効か確認したいとします。例えば
、ユーザがスケジュールで8月45日にパーティを開く予定を入力したり、未来の時間を誕生日にしてみたりといった場合です。
ユーザが入力した日時が有効か確認したいとします。例えばユーザがスケジュールで8月45日にパーティを開く予定を入力したり、未来の時間を誕生日にしてみたりといった場合です。
Goではtimeの処理パッケージを提供しています。ユーザの入力した年月日を目的の時間に変換してから、判断を行います。
@@ -142,7 +141,7 @@ Goではtimeの処理パッケージを提供しています。ユーザの入
timeを取得した後、多くの時間関数の操作を行うことができます。具体的な判断は自身の要件に合わせて調整してください。
## 身分証明書番号
フォームに入力された身分証を検証する場合、正規表現を使って簡単に検証できます。しかし身分証明書番号は15桁と18桁があるのでつとも検証しなければなりません。訳注中国では身分証明書とともに個人を特定する国民背番号があります。)
フォームに入力された身分証明書を検証する場合、正規表現を使って簡単に検証できます。しかし身分証明書番号は15桁と18桁があるのでつとも検証しなければなりません。訳注中国では身分証明書に個人を特定する身分証明番号(以前は15桁、現在は18桁)が記載されています。)
//15桁の身分証明書の検証。15桁はすべて数字です。
if m, _ := regexp.MatchString(`^(\d{15})$`, r.Form.Get("usercard")); !m {
@@ -154,7 +153,7 @@ timeを取得した後、多くの時間関数の操作を行うことができ
return false
}
以上よく使用されるサーバ側でのフォーム要素の検証をいくつかご紹介しました。このイントロダクションを通してGoによるデータ検証、特に正規表現での処理に対する理解が深まるよう願っています。
以上よく使用されるサーバ側でのフォーム要素の検証をいくつかご紹介しました。このイントロダクションを通してGoによるデータ検証、特に正規表現での処理に対する理解が深まるよう願っています。
## links
* [目次](<preface.md>)

View File

@@ -1,10 +1,10 @@
# 4.3 クロスサイトスクリプティングの予防
現在のホームページは大量の動的なコンテンツを含みユーザのエクスペリエンスを高めています。以前に比べてとても複雑になっています。いわゆる動的なコンテンツとはユーザの環境と要求により、Webアプリケーションが目的の内容を出力できることを指します。動的なホームページは"クロスサイトスクリプティング"(Cross Site Scripting、セキュリティ専門家が一般的にXSSと省略するもの)と呼ばれる攻撃を受けることがあります。
現在のホームページは大量の動的なコンテンツを含みユーザのエクスペリエンスを高めています。以前に比べてとても複雑になっています。いわゆる動的なコンテンツとはユーザの環境と要求に応じてWebアプリケーションが目的の内容を出力できることを指します。動的なホームページは"クロスサイトスクリプティング"(Cross Site Scripting、セキュリティ専門家が一般的にXSSと省略するもの)と呼ばれる攻撃を受けることがあります。
攻撃者は通常セキュリティホールのあるプログラム中にJavaScript、VBScript、ActiveXまたはFlashを挿入することでユーザを騙します。一旦攻撃が成功するとユーザアカウント情報が盗まれ、ユーザの設定を改ざんされてしまったり、cookieを盗みまたは汚染して悪意ある広告を埋め込んだりされます。
XSSに対する最も効果的な予防は以下の二種類を組み合わせることですすべての入力データを検証し攻撃の検査をすること(これに関しては前の節でいくつかご紹介しました)。もうひとつは出力されるデータに対し適切な処理を行うことによってすでに挿入されてしまったいかなるスクリプトに対してもブラウザで実行されないようにすることです。
XSSに対する最も効果的な予防は以下の二種類を組み合わせることですすべての入力データを検証し攻撃の検査をすることこれに関しては前の節でいくつかご紹介しました。もうひとつは出力されるデータに対し適切な処理を行うことによってすでに挿入されてしまったいかなるスクリプトに対してもブラウザで実行されないようにすることです。
Goではどのようにこの効果的な防御を行なっているのでしょうかGoのhtml/templateの中では以下のいくつかの関数によってエスケープすることができます。
@@ -47,7 +47,7 @@ Goのhtml/templateパッケージはデフォルトでhtmlタグをフィルタ
Hello, <script>alert('you have been pwned')</script>!
`template.HTML`に変換した後も変数の内容はエスケープされません。 
`template.HTML`に変換した後も変数の内容はエスケープされません。 
エスケープの例:

View File

@@ -1,8 +1,8 @@
# 4.4 フォームの複数回送信の防止
以前どこかのBBSやブログでご覧になったかもしれませんが、一つのスレや文章の後でいくつもの重複が記録されていることがあります。これらの大多数はユーザが複数回書き込みフォームを送信してしまったことによるものです。様々な原因でユーザはよくフォームを複数回送信してしまいます。通常はマウスの誤操作によるもので、送信ボタンをダブルクリックしてしまったり、一旦送信した内容を再度修正しようとして、ブラウザの戻るボタンを押した後に次へボタンではなくまた送信ボタンを押してしまうことによるものです。当然、故意によるものもあります。- - 例えばネット上のアンケート調査やくじ引きにおいて重複して投票するなどです。では、どのようにしてユーザが同じ内容のフォームの送信を行うことを効果的に防げるのでしょうか?
これまでにどこかのBBSやブログでご覧になったことがあるかもしれませんが、一つのスレッドや文章の後でいくつもの重複が記録されていることがあります。これらの大多数はユーザが複数回書き込みフォームを送信してしまったことによるものです。様々な原因でユーザはよくフォームを複数回送信してしまいます。通常はマウスの誤操作によるもので、送信ボタンをダブルクリックしてしまったり、一旦送信した内容を再度修正しようとして、ブラウザの戻るボタンを押した後に次へボタンではなくまた送信ボタンを押してしまうことによるものです。当然、故意によるものもあります。- - 例えばネット上のアンケート調査やくじ引きにおいて重複して投票するなどです。では、どのようにしてユーザが同じ内容のフォームの送信を行うことを効果的に防げるのでしょうか?
解決方法はフォームの中に唯一の値を持ったhiddenフィールドを追加することです。フォームを検証する際、この唯一の値を持ったフォームがすでに送信されているかどうか検証します。もしすでに送信されていれば、二回目の送信を拒絶します。そうでなければフォームに対して処理ロジックを行います。また、もしAjax形式で送信するフォームだった場合、フォームが送信された後javascriptによってフォームの送信ボタンを禁止します。
解決方法はフォームの中にユニークな値を持ったhiddenフィールドを追加することです。フォームを検証する際、このユニークな値を持ったフォームがすでに送信されているかどうか検証します。もしすでに送信されていれば、二回目の送信を拒絶します。そうでなければフォームに対して処理ロジックを行います。また、もしAjax形式で送信するフォームだった場合、フォームが送信された後javascriptによってフォームの送信ボタンを禁止します。
4.2節の例を改良してみましょう:
@@ -14,7 +14,7 @@
<input type="hidden" name="token" value="{{.}}">
<input type="submit" value="ログイン">
テンプレートの中に`token`というhiddenフィールドを追加しました。この値にはMD5(タイムスタンプ)によってユニークな値を割り当てます。この値をサーバに保存することでsessionによってコントロールは6章でどのように保存するか解説します)フォームが送信される際の判定に使うことができます。
テンプレートの中に`token`というhiddenフィールドを追加しました。この値にはMD5(タイムスタンプ)によってユニークな値を割り当てます。この値をサーバに保存することでsessionによコントロールは6章でどのように保存するか解説します)フォームが送信される際の判定に使うことができます。
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) //リクエストを受け取る方法
@@ -48,9 +48,9 @@
図4.4 tokenを追加した後クライアントが出力するソース情報
tokenはすでに出力値を持っていますので連続してページを更新することができます。この値が次々と変化するのがお分かりいただけるかと思います。このように毎回formが表示される時にユニークになるよう保証します。ユーザが送信するフォームは唯一性が保持されます。
tokenはすでに出力値を持っていますので連続してページを更新することができます。この値が次々と変化するのがお分かりいただけるかと思います。このように毎回formが表示される時にユニークになるよう保証します。ユーザが送信するフォームは唯一性が保持されます。
この解決方法は悪意の無い攻撃に対しても防止することができます。また悪意のあるユーザに対してもしばらく効果があります。その後、この悪意のある動機を捨てることができなかった場合は更に複雑な作業が必要となります。
この解決方法は悪意の無い攻撃に対しても防止することができます。また悪意のあるユーザに対してもしばらく効果があります。その後、ユーザーにこの悪意のある動機を捨てさせることができなかった場合は更に複雑な作業が必要となります。
## links
* [目次](<preface.md>)

View File

@@ -1,7 +1,8 @@
# 4.5 ファイルのアップロード処理
ユーザによるファイルのアップロードを処理したいとします。例えば、現在Instagramのようなホームページを作成しているとします。ユーザが撮影した写真を保存する必要があります。このような要求はどのように実現するのでしょうか
フォームにファイルをアップロードさせるためには、まずformの`enctype`属性を追加する必要があります。`enctype`属性には以下の3つの状態あります:
フォームにファイルをアップロードさせるためには、まずformの`enctype`属性を追加する必要があります。`enctype`属性には以下の3つの種類があります:
application/x-www-form-urlencoded 送信前にすべての文字列をエンコードする(デフォルト)
multipart/form-data 文字列に対してエンコードしません。ファイルのアップロードウィジェットを含むフォームを使用するときはこの値が必要です。

View File

@@ -1,5 +1,6 @@
# 4.6 まとめ
この一章ではGoでどのようにフォームの情報を処理するか学びました。ユーザのログインから、ファイルのアップロードの例で、Goがformの情報およびファイルをアップロードする手段についてご説明しました。しかし、フォームを処理する過程ではユーザの入力した情報を懸賞する必要があります。ホームページのセキュリティの重要性を考慮すると、データのフィルタリングは相当重要です。そのため、以降の章では異なる方面のデータフィルタリングをご説明します。同時にGoの文字列に対する正規表現についても述べます。
この一章ではGoでどのようにフォームの情報を処理するか学びました。ユーザのログインから、ファイルのアップロードの例で、Goがformの情報およびファイルをアップロードする手段についてご説明しました。しかしフォームを処理する過程ではユーザの入力した情報を検証する必要があります。ホームページのセキュリティの重要性を考慮すると、データのフィルタリングは相当重要です。そのため以降の章では異なる方面のデータフィルタリングをご説明します。同時にGoの文字列に対する正規表現についても述べます。
この一章を通してクライアントとサーバが如何にデータを互いにやりとりするか理解いただけたと思います。クライアントはデータをサーバシステムに渡し、サーバはデータを受け取って結果をクライアントにフィードバックします。