suin
記事一覧 > スイナシア > ローカルストレージを使ってiPhoneのcookie健忘症対策: ウェブアプリ開発者の立場から
ローカルストレージを使ってiPhoneのcookie健忘症対策: ウェブアプリ開発者の立場から
- 2009-9-13 16:43
- スイナシア in iPhone, Tips, JavaScript
iPhoneはcookieがしばしば勝手に消えるようだ。そのせいで、セッションが切れる。すると、GmailやDropboxなどのウェブアプリはログアウトしていまい、IDとパスワードを入力し直す手間が出るので、たちまち不便になる。
セッションが落ちるのは仕方がないとする。それでも、IDやパスワードの記憶ぐらいはしておきたい。iPhoneのキーボードでメールアドレスとパスワードを入力するのは、えらく苦痛だからだ。iPhone向けウェブアプリの開発者としては、できるだけユーザの不便を解消してやりたいはずだ。
iPhoneのsafariにはパスワードの記憶機能がない。その代替策として、パスワードなどをcookieに保存する方法が考えるかもしれない。mixiなどもこの方法だ。しかし、上で述べたが、iPhoneのcookieはよく無くなる。そこで、さらにcookieの代替策として、safariのローカルストレージを使う手がある。
ローカルストレージとは?
iPhoneのsafariにはjavascriptで使えるSQLiteが用意されている。ローカルストレージはcookieと違い、有効期限がない。つまり、勝手に消えることは永久的にない。ただし、次のような制約がある。
- データベースはドメインごと。したがって、他のドメインのデータベースを参照することはできない。(逆にできたら、セキュリティ的に怖い)
- データベースの容量は5MBまで。
ローカルストレージの詳細は、分かりやすくまとめている「Safari 3.1 に実装された「Client-side database storage (SQL API)」とは何か? - IT戦記:」をご覧いただきたい。
では、具体的にローカルストレージを使った、ID・パスワードの記憶機能の実装を紹介する。コード量は多いが、やっていることは大して複雑ではない。
まずは、HTMLは次のように書く。
<form name="login" action="login.php" method="post" onsubmit="return emai_pass_remaind()"> <input type="text" name="email" value="" placeholder="メールアドレス" autocorrect="off" autocapitalize="off" /><br /> <input type="password" name="pass" value="" placeholder="パスワード" autocorrect="off" autocapitalize="off" /><br /> <input type="checkbox" name="save_pass" value="1" />メアドとパスワードを記憶<br /> <input type="submit" value="送信" /> </form>
つぎに、javascriptは次のように書く。
// ロード時に、データベースからメアドとパスワードを取得、フォームにセットする関数
window.onload = function() {
var db = openDatabase('mydatabase', '1.0');
db.transaction(
function(tx)
{
tx.executeSql("SELECT email, pass FROM login WHERE id = 1", [],
function(tx, rs)
{
// ロードに成功したら、フォームに値をセット
document.login.email.value = rs.rows.item(0).email; // htmlspecialchars?
document.login.pass.value = rs.rows.item(0).pass;
document.login.save_pass.checked = true;
}
);
}
);
}
// フォーム送信時に、メアドとパスワードをデータベースに保存・削除する関数
function emai_pass_remaind()
{
// フォームから値を取得
var email = document.login.email.value;
var pass = document.login.pass.value;
/* ここらへんにvalidationの処理を入れたり... */
var db = openDatabase('mydatabase', '1.0');
if ( document.login.save_pass.checked == true )
{
db.transaction(
function(tx) {
// テーブルがあるかな?
tx.executeSql("SELECT count(*) FROM login", [],
function(tx, rs) {
// テーブルあるよ
if ( rs.rows.item(0) == 0 )
{
// テーブル初利用の場合は、追加
tx.executeSql('INSERT INTO login VALUES(1, ?, ?)', [email, pass], // escape?
function() {},
function(error) {
alert('save failed: ' + error.message);
}
);
}
else
{
// テーブル初利用じゃない場合は、更新
tx.executeSql('UPDATE login SET email = ?, pass = ? WHERE id = 1', [email, pass], // escape?
function() {},
function(error) {
alert('update failed: ' + error.message);
}
);
}
},
function(tx, error) {
// テーブルないよ、テーブルつくろ
tx.executeSql('CREATE TABLE login (id INTEGER PRIMARY KEY, email TEXT, pass TEXT)', [],
function() {
// テーブル初利用だから、追加
tx.executeSql('INSERT INTO login VALUES(1, ?, ?)', [email, pass], // escape?
function() {},
function(error) {
alert('save failed: ' + error.message);
}
);
},
function(error) {
alert('Database creation failed.' + error.message);
}
);
}
);
}
);
}
else
{
// チェックボックスにチェックがないときは、テーブル削除
db.transaction(
function(tx) {
tx.executeSql('DROP TABLE login', [],
function() {},
function(error) {
alert('delete failed: ' + error.message);
}
);
}
);
}
}
これで、あなたのウェブアプリも、かなり便利になると思う。

