Merge commit 'd0cf4af651354a785c821b7887cf2ca55ec83450' into ja
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# 8 Webサービス
|
||||
WebサービスではHTTPプロトコルの基礎の上にXMLまたはJSONを使って情報を交換することができるようになります。もし上海の天気予報を知りたかったり、チャイナペトロの株価やタオバオの商店にある商品の情報を知りたかったりすると、簡単なコードを少し書くことで、これらの情報を取得し、標準のインターフェースに開放することができます。ローカルで関数をコールし、値をひとつ返すのと同じようなものです。
|
||||
WebサービスではHTTPプロトコルの基礎の上にXMLまたはJSONを使って情報を交換することができるようになります。もし上海の天気予報やチャイナペトロの株価やタオバオの商店にある商品の情報を知りたいとすると、簡単なコードを少し書くことでこれらの情報を標準的なオープンインターフェースを介して取得することができます。ローカルで関数をコールすると値をひとつ返すのと同じようなものです。
|
||||
|
||||
Webサービスのバックエンドのキーはプラットフォームに依存しないことです。あなたはあなたのサービスをLinuxシステムで実行してもかまいませんし、他のWindowsのasp.netプログラムと交互に同様に一つのインターフェースを通じてFreeBSD上で実行されているJSPとなんの障害も無く通信することもできます。
|
||||
|
||||
@@ -7,9 +7,9 @@ Webサービスのバックエンドのキーはプラットフォームに依
|
||||
|
||||
RESTリクエストはとても直感的です。なぜならRESTはHTTPプロトコルに基いた追加だからです。各リクエストはどれもHTTPリクエストです。異なるmethodに従って異なるロジックを処理します。多くのWeb開発者はいずれもHTTPプロトコルに詳しいので、RESTを学ぶことは比較的簡単でしょう。ですので我々は8.3節においてどのようにGo言語でRESTメソッドを実装するか詳細にご紹介します。
|
||||
|
||||
SOAPはW3Cのネットワークを超えた情報伝達とリモートコンピュータの関数コール方面の標準のひとつです。しかしSOAPはとても複雑で、完全な規則は非常に長くなります。また内容はいまでも増加しています。Go言語は簡単さで有名ですので、SOAPのような複雑なものはここではご紹介しません。Go言語は生まれながらにしてとても良い、開発に便利なRPCメカニズムを提供しています。8.4節ではどのようにしてGo言語を使ってRPCを実装するか詳しくご紹介するつもりです。
|
||||
SOAPはW3Cのネットワークを超えた情報伝達とリモートコンピュータの関数呼び出し規約の標準のひとつです。しかしSOAPはとても複雑で、完全な規則は非常に長くなります。また内容はいまでも増加しています。Go言語は簡単さで有名ですのでSOAPのような複雑なものはここではご紹介しません。Go言語は生まれながらにしてとても良い、開発に便利なRPCメカニズムを提供しています。8.4節ではどのようにしてGo言語を使ってRPCを実装するか詳しくご紹介するつもりです。
|
||||
|
||||
Go言語は21世紀のC言語です。性能と簡単さを追求するため、8.1節ではどのようにしてSocketプログラミングを行うかご説明します。多くのゲームサービスはどれもSocketを採用してサーバをプログラムしています。HTTPプロトコルは比較的性能を必要とするものですので、Go言語がどのようにしてSocketプログラミングを行うのか見てみることにしましょう。現在HTML5の発展にしたがって、webSocketsも多くのゲーム会社が引き続き開発する手段の一つとなりつつあります。8.2節ではGo言語でどのようにしてwebSocketsのコードをプログラムするかご説明します。
|
||||
Go言語は21世紀のC言語です。性能と簡単さを追求するため、8.1節ではどのようにしてSocketプログラミングを行うかご説明します。多くのゲームサービスはどれもSocketを採用してサーバをプログラムしています。HTTPプロトコルは比較的性能を必要とするものですので、Go言語がどのようにしてSocketプログラミングを行うのか見てみることにしましょう。現在HTML5の発展にしたがって、WebSocketも多くのゲーム会社が引き続き開発する手段の一つとなりつつあります。8.2節ではGo言語でどのようにしてWebSocketのコードをプログラムするかご説明します。
|
||||
|
||||
## 目次
|
||||

|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# 8.1 Socketプログラミング
|
||||
多くの低レイヤのネットワークアプリケーションの開発者の目には一切のプログラムがどれもSocketのように映ります。すこし大げさかもしれませんが、だいたいこのようなものです。現在のネットワークプログラミングはほぼすべてにおいてSocketを使用してプログラムされています。このような場面を考えたことはありませんか?毎日ブラウザを開いてページを閲覧する際、ブラウザプロセスはどのようにしてWebサーバと通信を行なっているのでしょう?QQを使ってチャットする時、QQプロセスはどのようにしてサーバまたはあなたの友達がいるQQプロセスと通信を行なっているのでしょう?PPstreamを開いてストリーミング映像を見るとき、PPstreamプロセスはどのようにして動画サーバと通信をおこなっているのでしょう?このように、すべてはSocketに依存して通信を行なっています。ひとつを見てすべてを理解すると、Socketプログラミングは現代のプログラミングの中でも非常に多くの重要な地位を占めていることが見て取れます。この章ではGo言語においてどのようにSocketプログラミングを行うのかご紹介します。
|
||||
多くの低レイヤのネットワークアプリケーションの開発者の目には一切のプログラムがどれもSocketのように映ります。すこし大げさかもしれませんが、だいたいこのようなものです。現在のネットワークプログラミングはほぼすべてにおいてSocketを使用してプログラムされています。このような場面を考えたことはありませんか?毎日ブラウザを開いてページを閲覧する際、ブラウザプロセスはどのようにしてWebサーバと通信を行っているのでしょう?QQを使ってチャットする時、QQプロセスはどのようにしてサーバまたはあなたの友達がいるQQプロセスと通信を行なっているのでしょう?PPstreamを開いてストリーミング映像を見るとき、PPstreamプロセスはどのようにして動画サーバと通信を行っているのでしょう?このように、すべてはSocketに依存して通信を行なっています。ひとつを見てすべてを理解すると、Socketプログラミングは現代のプログラミングの中でも非常に多くの重要な地位を占めていることが見て取れます。この章ではGo言語においてどのようにSocketプログラミングを行うのかご紹介します。
|
||||
|
||||
## Socketとは何か?
|
||||
SocketはUnixを起源とします。Unixの基本哲学の一つは"すべてはファイルである"です。すべては"開くopen -> 読み書きwrite/read -> 閉じるclose"のパターンによって操作されます。Socketはこのパターンの実装の一つです。ネットワークのSocketデータ通信は特殊なI/Oの一つです。Socketもファイルディスクリプタの一種です。Socketもファイルを開く関数を持っています:Socket()。この関数はint型のSocketディスクリプタを返します。以後の接続の確立によってデータ転送といった操作はすべてこのSocketを通ることで実現されます。
|
||||
@@ -10,7 +10,7 @@ SocketはUnixを起源とします。Unixの基本哲学の一つは"すべて
|
||||
|
||||

|
||||
|
||||
图8.1 七層のネットワークプロトコルの図
|
||||
図8.1 七階層のネットワークプロトコルの図
|
||||
|
||||
TCP/IPプロトコルを使用したアプリケーションプログラムは通常アプリケーションプログラムのポートを採用します:UNIX BSDのソケット(socket)とUNIX System VのTLI(すでに淘汰されています)によってネットワークプロセス間の通信を実現します。現在ではほぼすべてのアプリケーションプログラムではsocketが採用されています。現在はネットワーク時代で、ネットワークのプロセス通信はどこにでも存在します。"すべてがSocket"というのはこういうことです。
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ WebSocketはクライアントとサーバに分けられます。ここでは
|
||||
|
||||
図8.4 WebSocketサーバが受け取った情報
|
||||
|
||||
上の例でクライアントとサーバでWebSocketを実装するのが非常に簡単だとわかりました。Goのソースコードのnetブランチではすでにこのプロトコルが実装されており、直接持ってきて使用することができます。現在HTML5の発展にしたがって将来WebSocketがWeb開発の充填になると考えています。我々はこの方面の知識を蓄える必要があります。
|
||||
上の例でクライアントとサーバでWebSocketを実装するのが非常に簡単だとわかりました。Goのソースコードのnetブランチではすでにこのプロトコルが実装されており、直接持ってきて使用することができます。現在HTML5の発展にしたがって将来WebSocketがWeb開発にとって重要になると考えています。我々はこの方面の知識を蓄える必要があります。
|
||||
|
||||
|
||||
## links
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 8.3 REST
|
||||
RESTful、とは現在もっとも流行しているインターネットソフトウェアフレームワークです。構造が明瞭で、標準に合っており、理解しやすく、拡張に便利です。そのため、まさに多くのホームページで採用されつつあります。この節ではこれが一体どのようなフレームワークなのか、Goではどのようにして実現するのかを学んでいきます。
|
||||
## RESTとは何か
|
||||
REST(Representational State Transfer)という概念は2000年Roy Thomas Fielding(彼はHTTPルールの主な編集者の一人です。)の博士論文の中で現れました。この中ではあるフレームワークの制約条件と原則について触れています。これらの制約条件と原則を満足したアプリケーションまたは設計はRESTfulということです。
|
||||
REST(Representational State Transfer)という概念は2000年Roy Thomas Fielding(彼はHTTP仕様の主な著者の一人です。)の博士論文の中で初めて登場しました。この中ではあるフレームワークの制約条件と原則について触れています。これらの制約条件と原則を満足したアプリケーションまたは設計はRESTfulということです。
|
||||
|
||||
RESTが何かを理解するためには、以下のようないくつかの概念を理解する必要があります:
|
||||
|
||||
@@ -107,7 +107,7 @@ GoにはRESTに対する直接のサポートはありません。しかし、RE
|
||||
上のコードではどのようにRESTなアプリケーションを書くかご覧いただきました。我々がアクセスするリソースはユーザです。異なるmethodによって異なる関数にアクセスしました。ここではサードパーティライブラリ`github.com/drone/routes`を使用しています。前の章でどのように自分で定義したルータを実現するかご紹介しました。このライブラリは自分で定義したルートと便利なルートのルールを反映させます。これを使って簡単にRESTのフレームワークを実装することができます。
|
||||
|
||||
## まとめ
|
||||
RESTはフレームワークスタイルの一種です。WWWの成功経験を汲み取っています:ステートレス、リソースを中心とし、HTTPプロトコルとURIプロトコルを十分利用しています。統一したインターフェース定義を提供し、Webサービスを設計する方法の一つとして流行しました。ある意味で、URIとHTTPといった黎明期のInternet標準を強調することで、RESTは大型のアプリケーションプログラムサーバ時代の前のWeb方式に回帰しています。現在GoはRESTに対するサポートはやはり簡単です。自分dね定義したルーティングを通して、異なるmethodに異なるhandleを実装することができます。このようにRESTのフレームワークは実現されています。
|
||||
RESTはフレームワークスタイルの一種です。WWWの成功経験を汲み取っています:ステートレス、リソースを中心とし、HTTPプロトコルとURIプロトコルを十分利用しています。統一したインターフェース定義を提供し、Webサービスを設計する方法の一つとして流行しました。ある意味でURIとHTTPといった黎明期のInternet標準を強調することで、RESTは大型のアプリケーションプログラムサーバ時代の前のWeb方式に回帰しています。今のところGoのRESTに対するサポートはまだシンプルです。自分で定義したルーティングを通して、異なるmethodに異なるhandleを実装することができます。このようにRESTのフレームワークは実現されています。
|
||||
|
||||
## links
|
||||
* [目次](<preface.md>)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# 8.4 RPC
|
||||
前の節でどのようにSocketとHTTPに基づいてネットワークアプリケーションを書くかご紹介しました。SocketとHTTPが採用しているのは"情報交換"パターン、すなわちクライアントがサーバに情報を一つ送信し、その後(一般的に)サーバが一定の情報を返すことでレスポンスとする、ようなものであると理解しました。双方は互いが発生させた情報を解析できるように、クライントとサーバ間が情報をやり取りする形式が締結されます。しかし独立した多くのアプリケーションは特にこのようなパターンを採用はしません。その代わり通常の関数をコールするのに似た方法で必要となる機能を完成させます。
|
||||
前の節でどのようにSocketとHTTPに基づいてネットワークアプリケーションを書くかご紹介しました。SocketとHTTPが採用しているのは"情報交換"パターン、すなわちクライアントがサーバに情報を一つ送信し、その後(一般的に)サーバが一定の情報を返すことでレスポンスとする、ようなものであると理解しました。双方は互いが発生させた情報を解析できるように、クライアントとサーバ間で情報をやり取りする形式が取り決められています。しかし多くの独立したアプリケーションは特にこのようなモデルを採用していません。その代わり通常の関数をコールするのに似た方法で必要となる機能を実現しています。
|
||||
|
||||
RPCは関数をコールするモデルをネットワーク化したものです。クライアントはローカルの関数をコールするのと同じように、引数をひっくるめてネットワークを通じてサーバに送信します。サーバでは処理の中でそれを展開し実行します。そして、実行結果をクライアントにフィードバックします。
|
||||
|
||||
RPC(Remote Procedure Call Protocol) 、このリモートプロセスのコールプロトコルは、ネットワークを通してリモートコンピュータのプログラムにおいてリクエストするサービスです。低レイヤのネットワーク技術におけるプロトコルを理解する必要はありません。これは何らかの転送プロトコルの存在を仮定します。例えばTCPまたはUDPです。通信を行うプログラム間で情報データを簡単にやりとりすることができます。これを使って関数をコールするモデルをネットワーク化することができます。OSIネットワーク通信モデルで、RPCはデータリンク層とアプリケーション層を飛び越えます。RPCはネットワーク分散型の複数プログラムを含めてアプリケーションプログラムの開発を用意にします。
|
||||
RPC(Remote Procedure Call Protocol) 、このリモートプロセスのコールプロトコルは、ネットワークを通してリモートコンピュータのプログラムにおいてリクエストするサービスです。低レイヤのネットワーク技術におけるプロトコルを理解する必要はありません。これは何らかの転送プロトコルの存在を仮定します。例えばTCPまたはUDPです。通信を行うプログラム間で情報データを簡単にやりとりすることができます。これを使って関数をコールするモデルをネットワーク化することができます。OSIネットワーク通信モデルで、RPCはデータリンク層とアプリケーション層を飛び越えます。RPCはネットワーク分散型の複数プログラムを含めてアプリケーションプログラムの開発を容易にします。
|
||||
|
||||
## RPCの動作原理
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
CleanMap["name"] = name
|
||||
}
|
||||
|
||||
上面代码中我们初始化了一个CleanMap的变量,当判断获取的name是`astaxie`、`herry`、`marry`三个中的一个之后
|
||||
上のコードではCleamMapという変数をひとつ初期化しています。取得したnameが`astaxie`、`herry`、marry`の3つの打ちの一つだと判断した後、データをCleanMapに保存します。このようにCleanMap["name"]のなかのデータが合法であると保証することができます。そのためコードの他の部分にもこれを使用します。当然else部分に非合法なデータの処理を追加してもかまいません。再度フォームを表示しエラーを表示するといったこともできます。しかしフレンドリーに汚染されたデータを出力してはいけません。
|
||||
|
||||
上の方法はすでに知っている合法な値のデータをフィルタリングするのには有効ですが、すでに合法な文字列で構成されていると知っているデータをフィルタリングする場合はなんの助けにもなりません。例えば、ユーザ名をアルファベットと数字のみから構成させたいとする場合です:
|
||||
|
||||
@@ -53,7 +53,7 @@ MSSQLサーバは後ろのシステムに新しいユーザを追加するコマ
|
||||
|
||||
SQLインジェクション攻撃の被害はこれだけ大きく、どのように予防すればよいのでしょうか?以下のこれらの提案はひょっとしたらSQLインジェクションの予防に一定の助けとなるかもしれません。
|
||||
|
||||
1. Webアプリケーションのデータベースの操作権限を厳格に制限する。このユーザにはその作業に必要となる最低限の権限だけを与え、最大限注入攻撃がデータベースに与える被害を減少させる。
|
||||
1. Webアプリケーションのデータベースの操作権限を厳格に制限する。このユーザにはその作業に必要となる最低限の権限だけを与え、できる限りSQLインジェクション攻撃がデータベースに与える被害を減少させる。
|
||||
2. 入力されたデータが期待するデータ形式であるか検査し、変数の型を厳格に制限する。例えばregexpパッケージを使ってマッチング処理を行ったり、strconvパッケージを使って文字列を他の基本型のデータに変換することで判断する。
|
||||
3. データベースに入ってくる特殊文字('"\角括弧&*;等)に対してエスケープ処理を行う。またはエンコードする。Goの`text/template`パッケージには`HTMLEscapeString`関数があり、文字列に対してエスケープ処理を行うことができます。
|
||||
4. すべての検索クエリにはなるべくデータベースが提供するパラメータ化検索インターフェースを使用する。パラメータ化されたクエリはパラメータを使用し、ユーザが入力した変数をSQLクエリに埋め込みません。すなわち、直接SQLクエリを組み立てないということです。例えば`database/sql`の検索関数`Prepare`と`Query`を使ったり、`Exec(query string, args ...interface{})`を使います。
|
||||
|
||||
@@ -86,4 +86,4 @@ Go言語のこの三種類の暗号化アルゴリズムの実装は以下の通
|
||||
## links
|
||||
* [目次](<preface.md>)
|
||||
* 前へ: [入力のフィルタリングを確実に行う](<09.4.md>)
|
||||
* 次へ: [データを暗号化/復元する](<09.6.md>)
|
||||
* 次へ: [データを暗号化/復号する](<09.6.md>)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 9.6 データを暗号化/復元する
|
||||
# 9.6 データを暗号化/復号する
|
||||
前の節でどのようにしてパスワードを保存するかご紹介しました。しかしあるときには、慎重に扱うべきデータを暗号化して保存し、将来のあるときにいつでもそれらを復元したい場合があります。この時双方向暗号化アルゴリズムを使って我々の要求を満たさなければなりません。
|
||||
|
||||
## base64で暗号化/復元する
|
||||
## base64で暗号化/復号する
|
||||
もしWebアプリケーションが十分に簡単であれば、データのセキュリティにはそれほど厳格な要求があるわけではありません。ですので比較的簡単な暗号化である`base64`を採用することができます。このような方法は実装するのが比較的簡単で、Go言語の`base64`パッケージではすでにこれをよくサポートしています。下の例をご覧ください:
|
||||
|
||||
package main
|
||||
@@ -38,9 +38,9 @@
|
||||
}
|
||||
|
||||
|
||||
## 高度な暗号化/復元
|
||||
## 高度な暗号化/復号
|
||||
|
||||
Go言語の`crypto`では双方向暗号の高度な暗号化/復元パッケージがあります:
|
||||
Go言語の`crypto`では双方向暗号の高度な暗号化/復号パッケージがあります:
|
||||
|
||||
- `crypto/aes`パッケージ:AES(Advanced Encryption Standard)は、Rijndael暗号化アルゴリズムとも呼ばれます。アメリカの連邦政府が採用しているブロック暗号の標準の一つです。
|
||||
- `crypto/des`パッケージ:DES(Data Encryption Standard)は双方向暗号化標準のひとつです。これは現在秘密鍵のシステムに最も広く使用されています。特に金融データのセキュリティの保護で使われています。かつてアメリカ連邦政府の暗号化のスタンダードでしたがすでにAESにとってかわられています。
|
||||
@@ -59,14 +59,14 @@ Go言語の`crypto`では双方向暗号の高度な暗号化/復元パッケー
|
||||
var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
|
||||
|
||||
func main() {
|
||||
//暗号化したい文字列
|
||||
// 暗号化したい文字列
|
||||
plaintext := []byte("My name is Astaxie")
|
||||
//暗号化された文字列を渡すと、plaintは渡された文字列になります。
|
||||
// 暗号化された文字列を渡すと、plaintは渡された文字列になります。
|
||||
if len(os.Args) > 1 {
|
||||
plaintext = []byte(os.Args[1])
|
||||
}
|
||||
|
||||
//aesの暗号化文字列
|
||||
// aesの暗号化文字列
|
||||
key_text := "astaxie12798akljzmknm.ahkjkljl;k"
|
||||
if len(os.Args) > 2 {
|
||||
key_text = os.Args[2]
|
||||
@@ -81,13 +81,13 @@ Go言語の`crypto`では双方向暗号の高度な暗号化/復元パッケー
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
//暗号化文字列
|
||||
// 暗号化文字列
|
||||
cfb := cipher.NewCFBEncrypter(c, commonIV)
|
||||
ciphertext := make([]byte, len(plaintext))
|
||||
cfb.XORKeyStream(ciphertext, plaintext)
|
||||
fmt.Printf("%s=>%x\n", plaintext, ciphertext)
|
||||
|
||||
// 復元文字列
|
||||
// 復号文字列
|
||||
cfbdec := cipher.NewCFBDecrypter(c, commonIV)
|
||||
plaintextCopy := make([]byte, len(plaintext))
|
||||
cfbdec.XORKeyStream(plaintextCopy, ciphertext)
|
||||
@@ -110,10 +110,10 @@ Go言語の`crypto`では双方向暗号の高度な暗号化/復元パッケー
|
||||
Decrypt(dst, src []byte)
|
||||
}
|
||||
|
||||
この3つの関数は暗号化/復元操作を実現します。詳細な操作は上の例をご覧ください。
|
||||
この3つの関数は暗号化/復号操作を実現します。詳細な操作は上の例をご覧ください。
|
||||
|
||||
## まとめ
|
||||
この節ではいくつかの暗号化/復元アルゴリズムをご紹介しました。Webアプリケーションを開発している時は要求に合わせて異なる方法によって暗号化/複合を行うことができます。一般的なアプリケーションではbase64アルゴリズムを採用することができます。より高度な場合はaesやdesアルゴリズムを採用することができます。
|
||||
この節ではいくつかの暗号化/復号アルゴリズムをご紹介しました。Webアプリケーションを開発している時は要求に合わせて異なる方法によって暗号化/復号を行うことができます。一般的なアプリケーションではbase64アルゴリズムを採用することができます。より高度な場合はaesやdesアルゴリズムを採用することができます。
|
||||
|
||||
|
||||
## links
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# 11.1 エラー処理
|
||||
Go言語の主な設計は:簡潔、明瞭です。完結とは文法がCと似ていて、かなり簡単であるということです。明瞭とはいかなるキーワードも分かりやすいということを指しています。どのような隠された意味も含まず、エラー処理の設計でもこの思想は一貫しています。C言語では-1またはNULLをといった情報を返すことでエラーを表していることをご存知だと思います。しかしユーザからすると、対応するAPIの説明ドキュメントを見なければ、この戻り値がいったいどういう意味を表しているのかそもそもよくわかりません。例えば:0を返すと成功するのか失敗するのかといったことです。Goではerrorと呼ばれる型を定義することで、エラーを表しています。使用する際は、返されるerror変数とnilを比較することで操作が成功したか判断します。例えば`os.Open`関数はファイルのオープンに失敗した時にnilではないerror変数を返します。
|
||||
Go言語の主な設計方針は:簡潔、明瞭です。簡潔とは文法がCと似ていて、かなり簡単であるということです。明瞭とはいかなるキーワードも分かりやすいということを指しています。どのような隠された意味も含まず、エラー処理の設計でもこの思想は一貫しています。C言語では-1またはNULLをといった情報を返すことでエラーを表していることをご存知だと思います。しかしユーザからすると、対応するAPIの説明ドキュメントを見なければ、この戻り値がいったいどういう意味を表しているのかそもそもよくわかりません。例えば:0を返すと成功するのか失敗するのかといったことです。Goではerrorと呼ばれる型を定義することで、エラーを表しています。使用する際は、返されるerror変数とnilを比較することで操作が成功したか判断します。例えば`os.Open`関数はファイルのオープンに失敗した時にnilではないerror変数を返します。
|
||||
|
||||
func Open(name string) (file *File, err error)
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
- 9.3 [XSS攻撃の回避](09.3.md)
|
||||
- 9.4 [SQLインジェクションの回避](09.4.md)
|
||||
- 9.5 [パスワードの保存](09.5.md)
|
||||
- 9.6 [データを暗号化/復元する](09.6.md)
|
||||
- 9.6 [データを暗号化/復号する](09.6.md)
|
||||
- 9.7 [まとめ](09.7.md)
|
||||
* 10.[国際化とローカライズ](10.0.md)
|
||||
- 10.1 [デフォルトロケールの設定](10.1.md)
|
||||
|
||||
Reference in New Issue
Block a user