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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

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

Q&A

解決済

2回答

2871閲覧

電話番号もしくはメールアドレスでユーザ認証させたい

ssk

総合スコア332

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

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

0グッド

2クリップ

投稿2016/05/27 09:43

ユーザー認証を
・電話番号orメールアドレス
・パスワード

にしたいのですが、どのように書けば良いでしょうか。

PHP

1 $sql ='SELECT * FROM user WHERE tel=? OR mail=? AND password=?';

ここの部分を変えれば良いと思うのですが、どのように書けば良いかわかりません。
よろしくお願い致します。

全体のPHPは以下です。

PHP

1<?php 2try{ 3 $tel_mail=$_POST['tel_mail']; 4 $password=$_POST['password']; 5 //サニタイジング 6 $tel_mail=htmlspecialchars($tel_mail); 7 $password=htmlspecialchars($password); 8 $password=md5($password); 9 //データベース接続 10 require_once('./conf/db_con.php'); 11 $sql ='SELECT * FROM user WHERE tel=? OR mail=? AND password=?'; 12 $stmt=$dbh->prepare($sql); 13 $data[]=$tel_mail; 14 $data[]=$password; 15 $stmt->execute($data); 16 //1行ずつ取り出し 17 $rec = $stmt->fetch(PDO::FETCH_ASSOC); 18 $dbh=null; 19}catch(Exception $e){ 20 print 'ただいま障害により大変ご迷惑をお掛けしております。'; 21 exit(); 22} 23?>

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

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

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

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

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

guest

回答2

0

ベストアンサー

ツッコミどころ満載なので、コメントで。

php

1<?php 2 3// 開発中は必ず記述 4ini_set('display_errors', true); 5error_reporting(E_ALL); 6 7try { 8// $tel_mail = $_POST['tel_mail']; 9// $password = $_POST['password']; 10 $tel_mail = filter_input(INPUT_POST, 'tel_mail'); 11 $password = filter_input(INPUT_POST, 'password'); 12 13 $dbh = new PDO('mysql:dbname=testdb;host=localhost;charset=utf8' 14 , $username 15 , $passwd 16 , array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION)); 17 18 19 //サニタイジング 20// $tel_mail = htmlspecialchars($tel_mail); // <- 完全な間違い htmlspecialchars ダメ! 21// $password = htmlspecialchars($password); // <- 完全な間違い htmlspecialchars ダメ! 22 23 $sql = 'SELECT * FROM user WHERE (tel=:tel_mail OR mail=:tel_mail) AND password=:password'; 24 $stmt = $dbh->prepare($sql); 25 26 $data[':tel_mail'] = $tel_mail; 27 $data[':password'] = md5($password); // <- md5 なんて今時使うもんじゃないけど、本題ではないのでスルー 28 29 $stmt->execute($data); 30 31 //1行ずつ取り出し 32 $rec = $stmt->fetch(PDO::FETCH_ASSOC); 33} catch (Exception $e) { 34 print 'ただいま障害により大変ご迷惑をお掛けしております。'; 35 exit(); 36} 37

投稿2016/05/27 09:55

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

mpyw

2016/05/27 23:39

これたぶん有名な某書籍のやつですね…
ssk

2016/05/28 05:05

ありがとうございます。 はい、書籍を参考に書いていました。 新しい本だったのでセキュリティも問題ないかと思っていたのですが あまり良くないようですね、、 CertaiN様、Kosuke_Shibuya ご回答ありがとうございました。
退会済みユーザー

退会済みユーザー

2016/05/28 05:06

PHPの初心者向けの書籍ではあまり良書はないですねー。
guest

0

場当たり的な修正案に関してはKosuke_Shibuyaさんが既にコメントされているので,今後の実装の方針としてどうすればいいかについて.

PHPによる簡単なログイン認証いろいろ

こちらに認証機構の設け方についてまとめてあります.今回は「セッション認証」と称しているものに該当するかと思います.ただし, $hashes として設けているものは,データベース内に存在していると考えます.

コーディングに関するポイント

(セキュリティ上絶対に無視できないレベルで必須)

  • パスワードは直接記録したり脆弱なmd5は使わず,より強力なpassword_hashで作成したハッシュを取り扱う.
  • パスワードの照合はデータベース上では行わず,まずメールアドレス (UNIQUE制約のある前提) のみの指定で1件取り出してきておいて, 後からパスワードをpassword_verifyで検証して判定する.

(セキュリティ上多くの場合において必須)

  • セッションIDのハッシュ値を使ってCSRF対策を行う.
  • htmlspecialcharsは下処理の段階で適用してはいけない.逆に,HTMLとして表示する最終段階には絶対に適用を忘れないようにする.

(推奨)

  • PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTIONを指定し,あらゆる処理でPDOExceptionがハンドルできるようにする.
  • 例外発生でexitするときはheader("Content-Type: text/plain; charset=UTF-8", true, 500);を先に実行する.

運用に関するポイント

こちらは実運用する場合にのみ考えてください.練習用のサイトをローカルに立ち上げるだけでは気にしなくていいです.

(セキュリティ上絶対に無視できないレベルで必須)

  • パスワードを送信するページはTLSで暗号化する

(推奨)

  • 全てのコンテンツをTLSで暗号化する

投稿2016/05/27 23:57

mpyw

総合スコア5223

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

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

ssk

2016/05/28 06:00

CertaiN様 http://qiita.com/mpyw/items/bb8305ba196f5105be15 こちらのサイトを見て勉強しています。 以下の部分が理解できないのですが、 ただし, $hashes として設けているものは,データベース内に存在していると考えます。 ↑password_hashを利用して登録したユーザテーブルの事を指していますか? // 事前に生成したユーザごとのパスワードハッシュの配列 $hashes = [ 'ユーザ名' => '$2y$10$TThG3fsMJegLJHzVQbz8IeHhvpgBg7P5j6gjQWEUOrKKCtsA9L87G', ];
mpyw

2016/05/28 06:36

そうですね,ユーザ名と紐つけてパスワードハッシュをデータベースに格納してください.(この例は簡略化のために連想配列でハードコーディングしているだけです)
ssk

2016/06/12 01:32

mpyw様 お世話になっております。 上記の件、試しているのですが うまくいかず、困っています>< <?php include('header.php'); ?> <?php require_once __DIR__ . '/functions.php'; require_unlogined_session(); ini_set('display_errors', true); error_reporting(E_ALL); //ユーザから受け取ったユーザ名とパスワード $tel_mail = filter_input(INPUT_POST, 'tel_mail'); $password = filter_input(INPUT_POST, 'password'); try{ //データベース接続 include('./conf/db_con.php'); $sql ='SELECT * FROM user WHERE (tel=":tel_mail" OR mail=":tel_mail")'; $stmt=$dbh->prepare($sql); $data[':tel_mail'] = $tel_mail; $stmt->execute($data); $dbh = null; //1行ずつ取り出し $rec = $stmt->fetch(PDO::FETCH_ASSOC); // 事前に生成したユーザごとのパスワードハッシュの配列 $hashes = [ 'tel_mail' => $rec['password'], ]; }catch(Exception $e){ print 'ただいま障害により大変ご迷惑をお掛けしております。'; exit(); } // POSTメソッドのときのみ実行 if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ( validate_token(filter_input(INPUT_POST, 'token')) && password_verify( $password, isset($hashes[$tel_mail]) ? $hashes[$tel_mail] : '$2y$10$abcdefghijklmnopqrstuv' // ユーザ名が存在しないときだけ極端に速くなるのを防ぐ ) ) { // 認証が成功したとき // セッションIDの追跡を防ぐ session_regenerate_id(true); // ユーザ名をセット session_start();//合言葉を決める $_SESSION['login']=1;//ログインOKの証拠を残す $_SESSION['user_id']=$rec['user_id']; // ログイン完了後に / に遷移 header('Location: /'); exit; } // 認証が失敗したとき // 「403 Forbidden」 http_response_code(403); } header('Content-Type: text/html; charset=UTF-8'); ?> <main id="regist"><?php var_dump($hashes); ?> <div class="container"> <section class="container"> <form class="form-horizontal" action="" method="post"> <fieldset> <div class="clearfix"></div><br> <div class="input-group input-group-lg"> <span class="input-group-addon"><i class="glyphicon glyphicon-user red"></i></span> <input type="text" class="form-control" placeholder="電話番号またはメールアドレス" name="tel_mail"> </div> <div class="clearfix"></div><br> <div class="input-group input-group-lg"> <span class="input-group-addon"><i class="glyphicon glyphicon-lock red"></i></span> <input type="password" class="form-control" placeholder="パスワード" name="password"> </div> <div class="clearfix"></div> <div class="col-sm-12"> <button type="submit" class="btn btn-default center-block">ログイン</button> </div> </fieldset> <input type="hidden" name="token" value="<?=h(generate_token())?>"> </form> <?php if (http_response_code() === 403): ?> <p style="color: red;">ユーザ名またはパスワードが違います</p> <?php endif; ?> </section> </div> </main> <?php include('footer.php'); ?>
ssk

2016/06/12 01:33

まず、 <?php var_dump($hashes); ?> とすると array(1) { ["tel_mail"]=> NULL } と表示されてしまいます。 何が間違っているのでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問