maxlengthを使ってはいけない。特にパスワード入力欄で使っちゃ駄目！

今日自分が体験したトラブル事例に、ユーザビリティ向上のための気づきがあったのでメモしておきます。

※本文よりまず、__[このコメント](http://qiita.com/kawaz/items/d462a05c113b8e063736#comment-31858b02023fac3424de)__、こっちに言いたいことが集約されてるのでまずはこっちを読むと早いです。
※本文よりまず、__[このコメント](http://qiita.com/kawaz/items/d462a05c113b8e063736#comment-31858b02023fac3424de)__、こっちに言いたいことが集約されてるのでまずはこっちを読むと早いです。
※本文よりまず、__[このコメント](http://qiita.com/kawaz/items/d462a05c113b8e063736#comment-31858b02023fac3424de)__、こっちに言いたいことが集約されてるのでまずはこっちを読むと早いです。

# 事例：登録時のパスワードでログイン出来ない！？
今日、とあるWEBサイトでユーザ登録を行った際に、登録時に入力したパスワードでログイン出来ないというトラブルがありました。
普通は自分の入力ミスを疑うところですが、登録もログインもコピペで入力しているので入力ミスはありえ無いと思っていました。

## お問い合わせフォームからバグ報告
というわけでこれはバグだろうと、お問い合せフォームから以下のような内容の報告をしました。

> バグ報告
> 
> 新規登録時に設定するパスワード入力フォームでは20文字のパスワードで新規登録を行いました。
ですがそのパスワードでログインしようとするとパスワードが間違っているとのエラーでログインが出来ません。
> 仕方ないのでパスワード再発行ページから新しいパスワードを入力した所、パスワードは12文字以内というエラーが出ました。
> もしかしてと思い、最初に入力した20文字のパスワードの頭12文字だけを入力したらログインできてしまいました。
> 恐らく登録時にサーバ側では何も言わずに12文字で切って保存されているのではないでしょうか？
> 
> これは登録フォームのバグだと思うので修正された方が良いかと思います。

上記の問い合わせを行ってから30分ほどするとサポートから以下の返答がありました。

> サーバ側ではそのような処理を行ってないのですが、どこの登録フォームから登録したか教えてもらえますでしょうか？

なので、僕も確認のためにシークレットウィンドウを開いて、再度最初の登録からやりなおして再現手順を報告しなおすことにしました。

## 再度のお問い合せ報告
再現手順を確認してみた結果、僕の最初の報告内容に間違いがあったことに気が付いたので以下の内容の報告を再度行いました。

> 再度登録処理を行なってみたところ、先ほどの問い合わせに書いた内容とは少し違っていたようですので改めてご説明いたします。
> 
> ■問題の説明
> 問題のフォームですが、登録自体はどこから行なってもよく、新規登録時に送られてくる確認メール内のワンタイムURLをクリックした後のパスワード登録フォームが問題のフォームになります。
> 
> ここで僕は、他ウィンドウで生成したランダムな20文字のパスワードをフォームに **コピペで貼り付け** て登録をしました。
> ですがパスワードのinputタグに`maxlength="12"`が付いていたために実際は12文字以降の文字が削られており、 **実際フォームに入力されていたのは12文字だけ** でした。その為、サーバ側には12文字の値が送信されており問題なく登録が行われていた、というのが真相でした。
> 
> maxlengthがついたフォームは手動入力時には制限に気づけるかもしれませんが、コピペ入力の場合はエラーにもならず勝手に後ろがなくなるというのがブラウザの挙動です。
> これは特に、パスワードのように伏字になる入力欄でかつ12文字や20文字などの長い文字列では、後ろが削られたことに非常に気づきにくいです。
> その為、 **僕は20文字のパスワードを入力したと誤解したまま** 登録が完了してしまったわけです。
> 
> それに対してログインフォームのパスワード欄にはmaxlengthの指定がなく20文字の貼り付けが出来てしまうので、パスワードが一致しないという自体に陥っていたようです。
> 
> 
> ■対応方法
> 対応方法は2つあると思います。
> 
> 一つはログインフォームのパスワード入力欄にも maxlength="12" を付けてしまうことです。この場合は登録フォームと同様に余分な文字が勝手に削られるので同じくコピペでログインしようとする限りは気づかずにログインできてしまうでしょう。
> ですが、ユーザは「 **20文字のパスワードを設定したはず** 」と誤解したまま利用を続けることになり、将来的に入力フォームの改修があった際に同様の問題が顕在化する危険があります。
> 
> より良いのは、登録フォームのmaxlengthを外して12文字を超える入力が出来るようにした上で、Javascriptやサーバサイドでのチェックでエラー表示をすることだと思います。
> こうしたやりかたなら、ユーザは改めてパスワードは12文字までと意識した上で登録をすることになるので問題は起きにくいと思います。

# 教訓：最大長チェックはmaxlengthではなくJavascriptやサーバサイドでやろう！

ここで言うJavascriptってのは入力欄がリアルタイムで赤くなったり「12文字以内で入力してください」て横に表示されたりするアレのことです。
サーバサイドのチェックは当然しますが、フォーム側にmaxlengthが付いてるとサーバチェックが台無しになるのでmaxlengthは外しておきましょうってのが本記事の趣旨です。

## パスワード入力欄にmaxlengthを設定してはいけない

maxlengthが設定されていると、コピペ入力時に後ろの文字列が削られたことに気づかないということが分かりました。

**特にパスワード入力欄のような伏字のフォームでは後ろの文字が切れたことに気付けません！**

なので最大長を超えた入力を許した上で、Javascriptとサーバサイドのバリデーションでエラー表示をするのが親切だと思います。

## パスワード入力欄以外でもmaxlengthは使わないほうが良い

郵便番号や電話番号の入力欄でもハイフンや空白の考慮が無く、277-0001 と入力したつもりが 277-000 となったり、090-1234-5678 と入力したつもりが 090-1234-56 となってしまったりして、イラッとしながらハイフンを削った後に更に後ろの数字を入力しなおしたりといった経験があると思います。
こんな場合も maxlength は外しておいてくれた方が嬉しいです。

これもやはり最大長を超えた入力を許した上で、Javascriptとサーバサイドのバリデーションでエラー表示をするのが親切だと思います。

## 例外：使っても良いケース
例えばどういうケースで嬉しいか再度考えてみた。
その結果、変換不要で分割不要な1~4文字くらいまでの入力制限をしたい用途ならあってもいいのかな？と思えてきた。

- 4文字くらいまでの固定長の入力
    - 例えば暗証番号とかクレジットカードのセキュリティコードとか
    - 

もし他に目から鱗で便利になるケースがあるようでしたら参考までに是非教えてください！




# 補足
誤解される方もいるようなので補足しておきます。

ここでのmaxlengthの代わりのJavascript推奨は、あくまでUIの使い勝手向上の為であり、不正な値のポストを防ごうというのが目的ではありません。ぶっちゃけJSは無くても構いません。
ですが当然、 **サーバサイドでのバリデーションは必須** ですよ。

本質的にはJavascriptは不要で「maxlengthを外してサーバサイドバリデーション」これが提言の最小形です。