前提・実現したいこと
Next.jsでStaticGenerationのホームページを作成しています。
ホームページにはContactフォームを設置していて、APIにPOSTすると入力内容をメール送信されるようになっています。機能自体は完成しているのですが、セキュリティ観点でCSRF対策を入れたいと考えています。
方法としては、フォームのページにセッション情報を埋め込んで、POSTリクエスト時にクライアント側のJSからセッション情報を送信して、サーバ側で検証すれば良いのだと思いますが、フォームページにセッション情報を埋め込む方法がわかりません。
Next.jsの公式も読んだのですが、該当箇所がよくわかりませんでした。
全体的な理解が足りていないのかもしれませんが、このあたりの実装方法のヒントや参考文献についてお知恵を拝借できますと助かります。よろしくお願いします。
contact.js
javascript
1import Layout from "../components/layout" 2import Tags from "./tags" 3import SearchWindow from "./search_window" 4import { getUniqTags } from "../lib/posts" 5import axios from 'axios' 6 7export async function getStaticProps() { 8 9 const uniqTags = getUniqTags() 10 11 return { 12 props:{ 13 uniqTags 14 } 15 } 16 17} 18 19const submitFormData = (e) => { 20 e.preventDefault() 21 22 axios.post('/api/mailSender', 23 { 24 'company': company, 25 'nickname': nickname, 26 'email': email, 27 'question': question 28 } 29 ).then(() => { 30 var myModal = new bootstrap.Modal(document.getElementById('myModal')) 31 myModal.toggle() 32 }).catch((error) => { 33 console.log(error) 34 }) 35} 36 37export default function Contact({ uniqTags }) { 38 return( 39 <Layout> 40 <div className="container content"> 41 <div className="row"> 42 <div className="col-md-9 mb-5"> 43 <form onSubmit={submitFormData}> 44 <label htmlFor="company" className="form-label fw-bold">会社名 <span className="badge bg-secondary">任意</span></label> 45 <input maxLength="30" type="text" className="form-control mb-3" id="company" placeholder="会社名を記入してください"/> 46 <label htmlFor="nickname" className="form-label fw-bold">お名前(ニックネーム可) <span className="badge bg-danger">必須</span></label> 47 <input required maxLength="30" type="text" className="form-control mb-3" id="nickname" placeholder="お名前を記入してください"/> 48 <label htmlFor="email" className="form-label fw-bold">Eメールアドレス <span className="badge bg-danger">必須</span></label> 49 <input required maxLength="50" type="email" className="form-control mb-3" id="email" placeholder="メールアドレスを記入してください"/> 50 <label htmlFor="question" className="form-label fw-bold">お問い合わせ内容 <span className="badge bg-danger">必須</span></label> 51 <textarea required maxLength="1000" className="form-control mb-5" id="question" rows="7" placeholder="お問い合わせ、ご相談内容を記入してください"/> 52 <div className="d-flex justify-content-center"> 53 <input id="submitBtn" className="btn btn-success w-50" type="submit" value="この内容で送信する"/> 54 </div> 55 <div className="modal fade" id="myModal" data-bs-backdrop="static" data-bs-keyboard="false" tabIndex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true"> 56 <div className="modal-dialog"> 57 <div className="modal-content"> 58 <div className="modal-header"> 59 <h5 className="modal-title" id="staticBackdropLabel">送信完了</h5> 60 <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 61 </div> 62 <div className="modal-body"> 63 お問い合わせいただきありがとうございます。 64 </div> 65 <div className="modal-footer"> 66 <button type="button" className="btn btn-secondary" data-bs-dismiss="modal" onClick={closeModal}>Close</button> 67 </div> 68 </div> 69 </div> 70 </div> 71 </form> 72 </div> 73 <div className="col-md-3"> 74 <Tags uniqTags={uniqTags}/> 75 <SearchWindow /> 76 </div> 77 </div> 78 </div> 79 </Layout> 80 ) 81}
/api/mailSender.js
javascript
1import sgMail from '@sendgrid/mail' 2import Cors from 'cors' 3import initMiddleware from '../../lib/init-middleware' 4 5const mailto = process.env.NEXT_PUBLIC_MAILTO 6const mailkey = process.env.NEXT_PUBLIC_MAILKEY 7 8const cors = initMiddleware( 9 Cors({ 10 methods: ['POST'], 11 }) 12) 13 14export default async function handler(req, res) { 15 16 await cors(req, res) 17 18 if (req.method === 'POST') { 19 20 const company = req.body.company 21 const nickname = req.body.nickname 22 const email = req.body.email 23 const question = req.body.question 24 25 sgMail.setApiKey(mailkey) 26 const msg = { 27 to: mailto, 28 from: email, 29 subject: "フォームからのお問い合わせ", 30 html: `<p>お名前:${nickname}</p> 31 <p>会社名:${company}</p> 32 <p>お問い合わせ内容:${question}</p>`, 33 } 34 35 try { 36 await sgMail.send(msg) 37 console.log('Success to send mail') 38 res.status(200).send() 39 } catch(error) { 40 console.log(error) 41 res.status(500).send() 42 } 43 44 } else { 45 res.status(400).send() 46 } 47 48};
回答1件
あなたの回答
tips
プレビュー