
オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。
前回からだいぶ時間が経ってしまいました。
さて、前回までで、S3へサイトを移管する事が出来ましたが、サイトによっては問題が発生します。
そう、S3は単にストレージに過ぎないので、サーバサイドのプログラム(PHPなど)は動かすことが出来ません。
弊社のホームページですと、「問い合わせフォーム」が該当します。
旧サイトでは、「問い合わせフォーム」から問い合わせ内容をPOSTし、Webサーバ側のPHPファイルを実行し、メール送信処理を行っていました。
けれど、S3ではPHPを実行する事は出来ません。
という事で、代替案として、以下の方法を取ろうと思います。
・問い合わせフォームにて入力された内容を専用のS3バケットへテキストファイルとして保存
・S3バケットへの保存をトリガーに、Lambdaファンクションでメール送信
早速、実施して行きましょう。
1)identity poolの作成
まずは、AWSコンソール上のAmazon Cognitoのページへ。
・Step 1:Create identity pool
「Identity pool name」に適当な名前を設定し、「Enable access to unauthenticated identities」にチェックを付け、「Create Pool」を押します。

・Step 2:Set permissions
IAM Roleを選択します。
このタイミングで作成する事も可能なので、今回は、「Create a new IAM Role」を選択し、
Roleの名前を付けて、「Allow」を押します。

※Cognitoについては、こちらを参照。
そうすると、identity pool id が発行されるので、メモっておきます。

ここでやっている事は、『S3へファイルをアップロードする為の認証情報を作成している』、と思って頂ければ良いと思います。
2)IAM Roleへ権限付与
AWSコンソールで、IAM Roleを見ると、先程新規で作ったRoleが見れると思います。
次はこのRoleにS3へのファイルアップロード権限を付与します。
先程の画面でRoleをクリックすると、下記の画面に遷移しますので、
「Add inline policy」をクリックします。

・Visual editorでポリシー作成
JSONを直接貼り付けて説明しているサイトが多いのですが、それだと意味を理解しないで使ってしまうと思うんですよね。
と、言う訳で、視覚的にポリシー作成を行なって行きます。
「Choose a service」をクリックします。

まずはサービスの選択ですが、S3と検索ボックスに入力すると、S3が選べるので、クリックします。

続いてアクションですが、S3にファイルを格納(Put)する必要があるので、
「PutObject」と「PutObjectAcl」をチェックします。
(他にもたくさんのアクションがあるので、ここでも検索ボックスに「PutObject」と入力しておくと楽です。)

次に、対象となるバケットを選択します。
「Specific」を選択してから、「Add ARN」をクリックします。

表示されたポップアップでバケット名をします。(バケットは前もって作っておいて下さい)
バケット内のオブジェクトは全てを対象とします。

バケットを選んだ後はこんな感じになります。
確認後、「Review policy」をクリックします。

最後、ポリシーに名前を付けて、「Create policy」でポリシーを作成します。

出来上がったポリシーのjsonはこんな感じです。
結構な手順記載しましたが、内容自体はこれだけ。

3)CORSの設定
サイトがあるドメイン(S3バケット)と問い合わせ内容を保持するドメイン(S3バケット)は違うので、CORS(Cross-Origin Resource Sharing)を設定する必要があります。
これを設定しないと、後に用意するjavascriptプログラムから問い合わせファイルをアップロードすることが出来ません。
では、AWSコンソール上で、問い合わせ内容を保存するS3バケットを選択し、
Permissionsタブから、「CORS configuration」を選択し、編集を行います。

「AllowedOrigin」には、問い合わせフォームがあるサイトのドメイン(S3バケットURL)を指定します。
- <?xml version="1.0" encoding="UTF-8"?>
- <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
- <CORSRule>
- <AllowedOrigin>http://officekoma.co.jp.xxxxxxxxxxxxxxxxxx</AllowedOrigin>
- <AllowedMethod>PUT</AllowedMethod>
- <MaxAgeSeconds>3000</MaxAgeSeconds>
- <AllowedHeader>*</AllowedHeader>
- </CORSRule>
- </CORSConfiguration>
これを「*」にしてしまうと、先程のidentity pool idを知っていれば、そこら中のドメインからファイルがアップロード出来てしまうので要注意です。
4)問い合わせフォームとアップロードプログラムの作成
後は問い合わせフォーム(html)とアップロードプログラム(javascript)の作成です。弊社サイトの問い合わせフォームは以下のようになっています。
・問い合わせフォーム(html)
- <!doctype html>
- <html lang="ja">
- <head>
- <!-- 中略 -->
- <script src="https://sdk.amazonaws.com/js/aws-sdk-2.200.0.min.js"></script>
- <script src="../js/s3Upload.js"></script>
- <!-- 中略 -->
- </head>
- <body>
- <!-- 中略 -->
- <h1>お問い合わせはこちらからお願いします。</h1>
- <p>フォームからの送信に失敗する場合、お手数ですが <a href="mailto:info@officekoma.co.jp">info@officekoma.co.jp</a> まで直接ご連絡ください。<br>
- ※商品・サービスの売り込み、その他営業活動・勧誘などには返信できかねますのでご遠慮ください</p>
- <script type="text/javascript" src="../js/form-validation.js"></script>
- <div class="form_control setting_center">
- <form id="contactForm" action="#">
- <fieldset>
- <p>お名前または会社名(Name)<span class="required">※必須</span></p> <input name="name" id="name" type="text" class="form_box" autocomplete="name" required />
- <p>メールアドレス(Email)<span class="required">※必須</span></p><input name="email" id="email" type="text" class="form_box" autocomplete="email" required />
- <p>問い合わせ内容(Comments)<span class="required">※必須</span></p>
- <textarea name="comments" id="comments" class="form_box" rows="4" cols="40" ></textarea>
- <div class="input_submit"><input type="button" value="送信 " name="submit" id="submit" /></div>
- </fieldset>
- <p id="error" class="warning">送信に失敗しました。恐れ入りますが、再度入力をお願いします。</p>
- </form>
- <p id="success" class="success">お問合わせを送信いたしました。ありがとうございました。内容を確認後、早急にご返信させていただきます。もし数日中に返事が無い場合は、正しく受信できなかった可能性がありますので、恐れ入りますが再度のご連絡をお願いします。</p>
- </div>
- <!-- 中略 -->
- </body>
- </html>
・アップロードプログラム(javascript)
「contactBucketName」、「bucketRegion」、「IdentityPoolId」をそれぞれの環境に合わせて変更して下さい。
- jQuery(document).ready(function($) {
- var contactBucketName = 'homepage-contact';
- var bucketRegion = 'hogehoge';
- var IdentityPoolId = 'hogehoge:xxxxxxxxxxxxxxxxxxxxxxxxxxx';
- AWS.config.update({
- region: bucketRegion,
- credentials: new AWS.CognitoIdentityCredentials({
- IdentityPoolId: IdentityPoolId
- })
- });
- var s3 = new AWS.S3({
- params: {Bucket: contactBucketName},
- });
- // hide messages
- $("#error").hide();
- $("#success").hide();
- // on submit...
- $("#contactForm #submit").click(function() {
- $("#error").hide();
- //name
- var name = $("input#name").val();
- if(name == ""){
- $("#error").fadeIn().text("名前を入力してください。(Name required.)");
- $("input#name").focus();
- return false;
- }
- var email = $("input#email").val();
- if(email == ""){
- $("#error").fadeIn().text("メールアドレスを入力してください。(Email required.)");
- $("input#email").focus();
- return false;
- }
- var now = new Date();
- var obj = {"name":$("input#name").val(), "email":$("input#email").val() ,"comments":$("#comments").val(), "date": now.toLocaleString()};
- var blob = new Blob([JSON.stringify(obj, null, 2)], {type:'text/plain'});
- s3.putObject({Key: now.getTime() + ".txt", ContentType: "text/plain", Body: blob, ACL: "public-read"},
- function(err, data){
- if(err !== null){
- $("#error").fadeIn();
- }
- else{
- $("#success").fadeIn();
- $("#contactForm").fadeOut();
- }
- });
- });
- return false;
- });
5)動作確認
実際に問い合わせを行うと、下記のようにファイルがアップロードされます。
ちょっと長くなってしまいましたが、これでPHP無しでも、サイトからの問い合わせの内容を確認する事が出来るようになりました。
とは言うものの、これだと、毎回能動的にS3のバケットを確認しないと問い合わせが確認出来ないので、現実的はありません。
次回は、問い合わせ内容をメールで送信する方法を記事にします。
(なんだか本質とは離れていっていますが、一応「サイトのhttps化」の一環です。)
次回:Amazon S3 で サイト公開(HTTPS)する。(3)問い合わせフォーム準備編その2
前回:Amazon S3 で サイト公開(HTTPS)する。(2)S3での公開準備編
AWS , Cognito , HTTPS , Lambda , S3
いつもサイトを拝見させていただいております。
返信削除「問い合わせフォーム準備編その1」を参考にさせていただき、勉強をさせていただいていたのですが、Upload後にPostで405 (Method Not Allowed)、PUTで400 bat Requestが出てしまい、解消することが出来ず、困っています。差し支えなければお時間のある際にご教示いただけると幸いです。よろしくお願いいたします。
「3)CORSの設定」にて、PUTのみを許可するようにしているので、「Postで405 (Method Not Allowed)」については、想定通りの動きかと思います。
削除「PUTで400 bad Request」ですが、400番台のエラーは、クライアント側からサーバー(AWS)へのリクエスト値に問題があることが原因になりますので、既に確認して頂いてはいると思いますが、再度、JavaScript側で定義しているリクエスト値に問題ないか、ご確認ください。
特に、contactBucketName、bucketRegion、IdentityPoolIdが怪しいかな、と思います。
よろしくお願いします。
お忙しい中、ご回答いただきありがとうございます。
削除Postの405が想定通りの動きであること承知しました。
また、PUTのエラーについてはサイトの情報を基に再作成したところ、解消いたしました。
大変勉強になりました。引き続き勉強に励みます。
ありがとうございました!