ハニーポットフィールドを使用してBotの可能性が高い入力を検出する

# はじめに
本記事では、ハニーポットフィールドを実装して、画面上には表示されない隠しフォームへの入力を検出する処理を実装します。


# ハニーポットフィールドとは？
ハニーポットフィールドは、Webフォームに組み込まれたUI上からは見えない隠しフォームフィールドです。
すべてのフィールドに値を入力しようとする Bot の傾向を利用し、怪しい入力を検出します。
通常ユーザーが入力することのないこのフィールドに値が入力されていた場合、Botによる入力が疑われます。


# ゴール
ハニーポットフィールドを実装して、隠しフィールドにおける値の入力を検出します。下記のようなフォームを実装します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/fa712a12-af5c-142f-9882-d7a378df7086.png)


# ソース

## HTML

```index.html
    <h1>お問い合わせフォーム</h1>
    <form id="contactForm">
        ～～～
        <div class="honeypot">
            <label for="demo">ハニーポット</label>
            <input type="text" id="demo" name="demo" autocomplete="off">
        </div>
        ～～～
        <button type="submit">送信</button>
    </form>
```

<details><summary>index.html 全文</summary>

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ハニーポットフィールドのデモ</title>
    <link rel="stylesheet" href="./index.css">
</head>
<body>
    <h1>お問い合わせフォーム</h1>
    <form id="contactForm">
        <div>
            <label for="name">お名前：</label>
            <input type="text" id="name" name="name" required>
        </div>
        <div>
            <label for="email">メアド：</label>
            <input type="email" id="email" name="email" required>
        </div>
        <div class="honeypot">
            <label for="demo">ハニーポット</label>
            <input type="text" id="demo" name="demo" autocomplete="off">
        </div>
        <div>
            <label for="message">メッセージ：</label>
            <textarea id="message" name="message" required></textarea>
        </div>
        <button type="submit">送信</button>
    </form>
    <div id="result"></div>

    <script src="./index.js"></script>
</body>
</html>
```

</details>


## CSS

`display: none` で画面上にUIを表示されないようにします。

```css:index.css
.honeypot {
  display: none;
}
```

<details><summary>index.css 全文</summary>

```css:index.css
body {
  background-color: #f0f0f0;
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.honeypot {
  display: none;
}

h1 {
  color: #333;
  margin-bottom: 3%;
}

#contactForm {
  width: 50%;
  background-color: #fff;
  padding: 5%;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

#contactForm div {
  margin-bottom: 2%;
}

label {
  display: block;
  margin-bottom: 1%;
  color: #555;
}

input[type="text"],
input[type="email"],
textarea {
  width: 100%;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
  box-sizing: border-box;
}

textarea {
  height: 100px;
  resize: vertical;
}

button {
  width: 10%;
  margin: 0 45%;
  background-color: #4caf50;
  color: white;
  padding: 10px 15px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  transition: background-color 0.3s;
}

button:hover {
  background-color: #45a049;
}

#result {
  margin-top: 20px;
  font-size: 24px;
  font-weight: bold;
  text-align: center;
  padding: 10px;
  border-radius: 4px;
}
```

</details>


## javascript

```javascript
//　要素を取得
const honeypotField = document.getElementById('demo');
const resultDiv = document.getElementById('result');

// 要素に値が入ってるかチェック
if (honeypotField.value) {
    // 値が入っていた場合
    resultDiv.textContent = 'Botによる送信が検出されました。';
    resultDiv.style.color = 'red';
```

<details><summary>index.js 全文</summary>

```javascript
document.getElementById('contactForm').addEventListener('submit', function(e) {
    e.preventDefault();
    
    const honeypotField = document.getElementById('demo');
    const resultDiv = document.getElementById('result');

    if (honeypotField.value) {
        resultDiv.textContent = 'Botによる送信が検出されました。';
        resultDiv.style.color = 'red';
    } else {
        resultDiv.textContent = 'フォームが正常に送信されました。';
        resultDiv.style.color = 'green';
        // ～～～
    }
});
```

</details>


# 動作を確認

サーバを立ち上げて動作を確認します。

### ハニーポットに値が入ってる場合

デベロッパーツールからjsのスクリプトに下記を追加し疑似的に値が入るようにします。

```javascript
document.getElementById('demo').value = '～～～～';
```

ハニーポット要素に値が入っている事を検知しできています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/10a77f99-3017-9951-017b-1d32a933f358.png)



### ハニーポットに値が入っていない場合

正常に処理できてることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/e7ce9112-5309-e2d3-86bb-b7f9e3fa0f2c.png)