質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

1回答

8748閲覧

PHPのsessionを使ったログインについて

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

2クリップ

投稿2016/10/17 07:40

現在PHPを使ってログインシステムを作ろうとしています。

色々調べてみた結果が「session」を使ったログインシステムでした。

まだわからない事だらけですので詳しい方がいましたら教えていただけると助かります。

①セッションを使うログインの際にデータベースへの接続及びIDやパスワードの保存はしなくても良いでしょうか。

②セッションを使ってログインしているかどうかはセッションに入っている文字列で判断するのでしょうか。その場合、セッションの中にIDやパスワードは入れても大丈夫でしょうか。

よろしくお願いします。

<!DOCTYPE html> <head> <meta charset="UTF-8"> <title>ログイン</title> </head> <body> <form method="post" action="index.php"> <input type="text" name="userid"> <input type="password" name="password"> <input type="submit" value="ログイン"> </form> </body> </html>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

個人情報をデータベースに格納する際は暗号化処理を行うなど細心の注意を行って下さい。
またセッションは非常に便利ですが、セッションハイジャックというリスクがあります。
http://qiita.com/kmikmy/items/bf691fb468a4d0bc2a47
セッションはページを読み込むごとに使い捨てするくらいの感覚のほうがいいと思います。

よって、
1)ログインという行為自体、入力されたデータがDBの値と一致するかどうかで判断するものだと思います。
通常は入力データを暗号化し、すでに暗号化されたDBのデータと照合を行って判断します。
セッションを使うのであれば、ログインOKの判定が出た時点でトークンを発行し、別テーブルに保存し、ページを読み込む前に確認させるなど工夫してください。

2)駄目だと思います。
IDとパスワードを両方セッションに保存するのはいくらなんでも危険です。

投稿2016/10/17 07:52

takepieee

総合スコア686

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/10/17 08:06

コメントありがとうございます。 そもそもセッションがなんなのかよくわかっていません。。 1の「ログインという行為自体、入力されたデータがDBの値と一致するかどうかで判断するものだと思います。」 との事ですがこれはデータベースにuseridとpasswordのカラムを作ってログイン時にDBに接続→一致するかの判定→OKならログイン状態という事でしょうか。 パスワードはデータベースに保存していいのでしょうか。 またトークンや別テーブルなどの保存など知らない点がいくつかあります。 リンク先も読んでみたのですがもう少し詳しく知りたいです。
takepieee

2016/10/17 08:28 編集

> との事ですがこれはデータベースにuseridとpasswordのカラムを作ってログイン時にDBに接続→一致するかの判定→OKならログイン状態という事でしょうか。 その通りです。 重ねて言いますが、平文保存はしないでくださいね。 私がその方法で作るなら・・ですが、 1)DBを作り、ユーザID、ユーザ名、パスワード等を含むテーブルを作る。 2)更に認証OK用のテーブルを作り、ユーザID、トークン、ログイン時間、ステータス等を含む。 3)管理画面を作ってユーザ管理を行う。そこからユーザ名、パスワード等を入力させ、暗号化してDBに保存する。 4)ログイン画面を作り、ユーザ名、パスワードを入力、POSTされた情報をDBと照合、OKであればトークンを発行、ユーザIDを読み込み、ユーザIDとトークンと時間を認証OKのテーブルに保存する 5)要ログインのページを表示させる際に、そのセッションを読み込み、認証OKテーブルにその値があり、有効で、規定時間を経過していない等のチェックを行い、OKであれば表示させる。表示後にトークンを更新し、以前のトークンは無効にする。 大まかにいうとその流れでしょうか。。 トークンの発行は人によってそれぞれノウハウはあります。IPを取得したり時間を取得したりして混ぜ込んでいきますが、絶対条件は「ユニークな値であること」です。 簡単なトークンであれば $token = uniqid( rand() ); だけでもいいと思いますが。 「セッションと保存されている値が同じ」というのは本当は望ましくないので、トークンも保存する歳はハッシュ化したほうがいいと思います。 ログインシステムはPHP作る上で誰もが通る難関です。がんばってください。
退会済みユーザー

退会済みユーザー

2016/10/17 08:35

コメントありがとうございます。 また丁寧な解説ありがとうございます。 思ってたよりも複雑ですね。。 まず新しく知った「トークン」について調べてみます。
takepieee

2016/10/17 09:02

最初は時間が掛かると思いますが、作られたコードは多分おもったより短いと思いますよ。 ログインシステムはフレームワークやPearのライブラリを使って簡単に済ませる場合か、 フルスクラッチで作ってチーム以外誰にも教えないか、多分どちらかです。 なので、使われている数に比べて情報は意外に少ないかもしれません。公開しませんから。 今回のトークンを使ったログインはほんの一例です。 他の開発者の方は他の方法使っているかもしれません。 方法はいろいろありますし、PHPも5.5以上であればハッシュ化する方法も選択肢が増えます。 がんばってください。
退会済みユーザー

退会済みユーザー

2016/10/19 07:19

コメントありがとうございます。 セッションまだ苦戦しています。 セッションの記事を読めば読むほどよくわかなくなります。 例えばif (isset($_POST['loginId']) && isset($_POST['loginPassword'])){ で名前やパスを入力してもらいそれらをハッシュ化(md5などはNG)してデータベースに保存する場合(トークンは一旦置いています。)、それらの文字列(名前やパス)はデータベースに入れた後に今度はセッション変数に入れるという認識でよろしいのでしょうか。 前回のお話だとそこにトークンを使ってIPやらユニークな値を与えて。。。というお話だったと思うのですがそもそもセッションの役割が理解できていません。。 よろしくお願いします。
takepieee

2016/10/19 07:58 編集

まず「データを登録する」と「ログイン確認をする」は分けて考えて下さい。 文章だけでは伝わりづらいし、ソースを書くと果てしないので、 http://wp.me/p7YbFd-w こちらのデータがあると仮定して記述します。 PDOよりmysqliの方が好きなんです。すみません・・ ただしこちらはハッシュではなく暗号化&復号化としてopenssl_encryptとopenssl_decryptを使用しています。 この記事は分かりやすくするために処理を端折っていますので予めご了承ください。 これまで説明した方法でログインするのであればもう一つテーブル作っておきます。 CREATE TABLE `login_data` ( `id` int(10) NOT NULL PRIMARY KEY AUTO_INCREMENT, `staffid` int(10) DEFAULT NULL, `token` varchar(256) DEFAULT NULL, `available` int(4) DEFAULT NULL, `created` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `updated` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ) ENGINE=MyISAM DEFAULT CHARSET=utf8; ○データを登録する 記事に記述しています。セッションは不要です。 ○ログイン確認をする if (isset($_POST['loginId']) && isset($_POST['loginPassword'])){ で値を暗号化してstaff_dataと照合。 一致するデータが有れば他のデータ(名前とかIDとか)を読み込み、 トークンを発行してlogin_dataにstaff_data.idとtokenを格納しておきます。 ○ログインした状態のページを読み込む セッションでトークンを持っているかを確認。 持っていればlogin_dataを照合し、有効なデータかを確認。その後updatedの時間を更新してページを表示。 持っていなければログインページに飛ばす。 大まかな流れはこんな感じでしょうか。 いきなりフルスクラッチでログインページを作るというのは少々危険な気もしています。 cakePHP等フレームワークを使って作るのも手ですよ。
退会済みユーザー

退会済みユーザー

2016/10/19 09:28

コメントありがとうございます。 すごい勘違いしてました。 【会員登録】と【ログイン】は全く別だったんですね…。 【会員登録】開始=【ログイン】も開始みたいに一緒くたに考えてました…。 すごく簡単に会員登録だけ書くとこんな感じでしょうか。(すごく簡単に書いています) <?php $dsn = 'xxxx'; $user = 'xxxx'; $password = 'xxxx'; if (isset($_POST['loginId']) && isset($_POST['loginPassword'])){ //ハッシュ化 $userid=xxxxxxxxxxxxx; $password=xxxxxxxxxxxxx; $pdo = new PDO($dsn, $user,$password); $sql="INSERT INTO sample VALUES($userid,$password)"; $stmt = $pdo->prepare( $sql); $stmt->execute(); } ?> みたいな感じでハッシュ化してデータベースに格納=会員登録 で、セッション使って(ここはまだわかっていないです…)ユーザー確認=ログインOKという感じでしょうか。 間違えていたらご指摘ください。 よろしくお願いします。
takepieee

2016/10/19 10:16

SQL式がアレですが、流れとしてはそうです。 念のためXSS対策とプリペアドステートメント使用をお忘れなく。 http://qiita.com/mpyw/items/565b3670dd0c7f9162fa http://php.net/manual/ja/pdo.prepared-statements.php 簡単に流れだけセッションを使った他の部分を書いておきます。 セッションの簡単な使い方 http://php.net/manual/ja/book.session.php ○ ログインOK。トークン発行します <?php session_start(); $_SESSION['token'] = uniqid(rand()); setToken($_SESSION['token'], $userid); function setToken($token, $uid) { // insert文 } ?> ○ ログインページを表示します <?php session_start(); $token = $_SESSION['token']; unset($_SESSION['token']); // トークンが無ければログインページへ if(!$token) { header('Location: loginページ'); } // トークンからID抽出 $uid = tokenCheck($token); // 抽出出来なければログインページへ if($uid < 1) { header('Location: loginページ'); } else { // スタッフIDが存在するか $check = staffCheck($uid); // スタッフIDが存在しなければログインページへ if($check < 1) { header('Location: loginページ'); } } function tokenCheck($token) { // 略 $stmt = $dbh->prepare('SELECT staffid FROM login_data WHERE token = :token'); $stmt->bindParam(':token', $token); // return ID } function staffCheck($id) { // 略 $stmt = $dbh->prepare('SELECT name FROM staff_data WHERE id = :id AND available = 1'); $stmt->bindParam(':id', $id); // return 行数 } ?> <html> 会員ページ
退会済みユーザー

退会済みユーザー

2016/10/19 12:03

コメントありがとうございます。 前回の件での理解不足すいませんでした。 そうなると少しだけセッションについても…と気がしてきました。 1行ずつわかる範囲で確認してみます。
takepieee

2016/10/20 01:07

phpという言語は上から1行づつ読み込んで処理をします。 変数やセッションに値を格納した時に、意図する値を格納しているのかを var_dump($value); を変数格納後に差し込んで、常に確認を行う癖をつけて下さい。 var_dump($_POST); var_dump($_SESSION); みたいに全体を見たい時にも有効です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問