薬剤師のプログラミング備忘録

普通の考え方ができない薬剤師の独り言

暫く更新していませんでした。

今回はパスワードの再設定についてです。

元々、パスワードはハッシュ化(暗号化)されてdatabaseに保存されますので、管理者側からもその内容はわからないようになっています。

つまり、パスワードは管理者がdatabase経由で直接書き換えても意味が無いということです。

例えば、

id:test_san

PASS:test_pass

だった場合には、databaseへの登録内容は、

 

id:test_san

PASS:$5y$50$gagfglN4VHmuUDify/q/PjOoeUJBsNS2bKpAPOkeiuaIOkoi(適当)

 

として登録されます。AさんとBさんが同一のパスワードだったとしても、この暗号化された内容は異なるようになっています。

一部のハッシュアルゴリズムは解析可能(と言っても、高性能パソコンで長い時間をかけて)です。

 

パスワードに使える文字種 = 26 + 26 + 10 = 62
すべてのパスワードの総数 628 = 約218兆
試行に掛かる秒数 = 218兆÷20億 = 約11万秒 = 約30時間

 

上記の時間ぐらいで解析できるようですね。

実際には、ハッシュに加えてソルトやストレッチングなども考慮するようですが、php7.0からは非推奨なようです。cryptやMD5のようなものもありますが、一般的に現在ではphpからはpassword_hashが多く用いられているようです。cryptは互換性があるようですけれども。

と、このようにハッシュ化によるパスワード保護は比較的安全ではありますが、パスワードリマインダが使用できないというデメリットもあります。管理者側(もしくは自動)でパスワードを確認する作業ですね。なので、新パッケージは利用者側から上書きするしかありません。

結局は総当りで攻撃されると突破される可能性もありますので、あまりに回数の多い入力はIPblockなどの方法が必要となると思います。

 

f:id:MC753:20170807170240g:plain

f:id:MC753:20170807170243g:plain

f:id:MC753:20170807170247g:plain

f:id:MC753:20170807170251g:plain

今日の進捗 処方登録フォーム:anamnese欄の追加

少し飲んでしまったので、あまり進んではいませんが、処方登録フォームにanamneseの欄を追加しました。少しだけ、それっぽくなってきました。

それと今日初めて知ったのですが、htmlのtextareaにはvalueは使えないんですね。

そのまま<textarea>ここ</textarea>にphpを入れておけば、修正で下のページに戻っても記入したものが残っているようにできるようですね。

f:id:MC753:20170728031635g:plain

今日の進捗 個人情報の書き換え

登録型サイトとなると、自身の情報を登録する必要があります。

設定項目は少ないほどよいのですが、信憑性等々の問題も出てくるので、一応多めに設定しました。

 

となると、databaseへの入力も面倒になります。

 

1.phpでは、login中のユーザーからuserIDを判別、databaseで照合して、その人のデータを照合します。

 

userID:user-san (変更不可)

名前:user

ハンドルネーム:user-san-dayo

年齢:25

 

これをinputにvalueを用いて自動記入します。

<input name="userid" value="<?php echo htmlspecialchars($xxx['userID']);?>">という感じです。

 

これをinputのsubmitで送信ボタンから別ページに送信します。

(ここはaction=""にして、phpの処理に任せたほうが楽かもしれませんので、後々修正予定です)

 

飛ばされた2.phpでは、POSTされたデータをSESSIONの連想配列で管理します。

$_SESSION['postData'] = $_POST

という感じです。

これによって

$_SESSION['postData']['userID'] -> user-san

と表示できるようになります。

 

ここからは、処方登録と同じ流れです。

$sql = sprintf('UPDATE table SET name="%s" ...(略) ... WHERE  userID ="%s"',

mysqli_real_escape_string($database接続,$_SESSION['postData']['name']));

mysqli_real_escape_string($database接続,$_SESSION['postData']['userID']));

mysqli_query($database接続,$sql) or die(mysqli_error($database接続));

unset ($_SESSION['postData']);

で、登録完了です。

 

databaseから登録内容を引っ張ってきます。IDに関しては変更不可なのでinputタグのdisableと使っています。

(名前と表示名てすとが逆になっているのは気にしないでください)

f:id:MC753:20170727001931g:plain

パスワードはハッシュ化されており、管理者側からも見えないようになっていますので表示できません。

※別ページで上書きして再設定してもらうことになります。

f:id:MC753:20170727001934g:plain

横長なので見えにくいですが、MySQLの方でもdatabaseがしっかりと書き換えられているのがわかります。

f:id:MC753:20170727001938g:plain

f:id:MC753:20170727001942g:plain

勿論、マイページの方でも内容が変わっていることが確認できます。

f:id:MC753:20170727002413g:plain

そう言えば先週はスポーツファーマシストの研修に行ってました。やっぱり東京は暑い、というか蒸しますね。

 

前回まではinputからボタンを作成して、actionで飛ばされるページに?id=xxと指定して、URLからidのxxを切り取ってSQLに接続。そこから呼び出す形にしていましたが、普通に考えた a hrefのlinkでどうにかなりそうなので、改善しました。

ボタンが何個も出るより、リンクをクリックした方が楽ですしね。複数窓で見ることもできるので(Ctrl+左click)、こっちの方が遥かにいいですね。

具体的には

echo "<table>";
while ($結果 = mysqli_fetch_assoc($結果s)) {
echo "
<tr>
<td>Title:<a href='処方見るページ.php?id=",$結果['id'],"'>",$結果['題名'] ,"</a></td>
<td> 閲覧状況:", $結果['表示の可否'] ,"</td>
</tr>
";
}
echo "</table>";

ある一定以上(例えば25件以上)出るようであれば、">>次ページ"とかのリンク出るようにしてもいいかもしれませんね。cssで仮のフレームページみたいのを作ってもよいのかもしれません。

f:id:MC753:20170725001122g:plain

先日の進捗

処方のカラムに表示・非表示の内容を追加し、非表示設定の際は表示されないようにしました。

本来であれば、検索に表示されないようにしたいのですが、それはまた次回。

今回は、検索結果に、暫定で表示と非表示を表示されるようにして、閲覧ボタンをクリックすると、自動的に非表示の場合は別ページに飛ばされるようにしました。

 

if ($mysqli_fetch_assoc(SQLから呼び出した配列) !== "表示") {

 header('Locaton: 表示されませんページ.php');

 exit();

}

 

という感じです。SQLから呼び出した配列の中のカラム(表示・非表示)で、表示と入力して無い場合、つまり、非表示設定の場合&処方が削除されている(URLの?id=xxから手入力で処方を探した場合に飛んでしまうのを防ぐため)場合も同に自動的に表示されません.phpのページに飛ぶようにしてあります。

 

次回は、非表示設定のものを検索&最近登録された処方の欄に表示されないようにすることと、表示・非表示の設定画面を作成します。表示・非表示については、処方箋入力後の確認画面で決定できるようにしたらいいかな?

 

「ムコ」で検索

f:id:MC753:20170721012620g:plain

表示できる場合(|||は後ほどjavascriptで処理予定)

f:id:MC753:20170721012624g:plain

非表示設定、またはidが消失した(処方が削除された)場合

f:id:MC753:20170721012628g:plain

今日の進捗

学会(というか講習会)で出張していました。

池袋では雹が降ったらしいですね。間一髪、ギリギリ当たりませんでした。

10分遅れていれば直撃でした。危なかったです。

 

今回は、まず検索内容と直近の登録についてテーブル形式で表記するようにしました。テーブルタグをhtmlに呼び出して

echo "<table>";

 //mysqli_fetch_assocで$xxxsという名前に格納したdatabaseの各内容を連想配列で呼び出し、xxxという変数を定義します。
while ($xxx = mysqli_fetch_assoc($xxxs)) {
echo "

 //検索内容が存在する場合は列として呼び出し、行に題名、ID、formを作成して閲覧ボタンを並べる。

 //閲覧ボタンはxxxというnameでvalue=$xxx['id']をポストする。ただ、このpostする内容については修正済みなので、後ほど削除する予定。

<tr>

<td> Title:",$xxx['題名'],"</td>

<td> ID:",$xxx['ID'],"</td>
<td>
<form name='xxx' method='post' action='showpage.php?id=",$xxx['id'],"'>
<input type='submit' value='閲覧'>
<input type='hidden' name='xxx' value=",$xxx['id'],">
</form>
</td>
</tr>
";
}

 //最後にテーブルタグを閉じて終わり。
echo "</table>";

という感じで表記してます。正しいのかはわかりませんが。

閲覧ボタンを押すと、actionとしてshowpage(仮).php?id=xxxに飛ぶようにしています。

今思えばこれはinputじゃなくて普通にa hrefでリンクさせてもいいのかもしれません。後日いじってみます。

if (!isset($xxx['検索内容とdatabaseを照合'])) {

echo "検索された語句は存在しません";

} else { ~~~

というのを作ろうと思ったのですが、検索1個目の内容が表記されないようです。emptyでも同様でした。詳しくは調べてみようと思います。

ついでに総処方登録数も表記するようにしました。

databaseのidの最終文字を取得しようと思いましたが、idはauto incrementで入力してあるので、処方データを消されたらぐちゃぐちゃになってしまいます。

ので、mysqli_queryで"SELECT * FROM table"からSQLのテーブルを呼び出して、 mysqli_num_rowsでレコード数のみを算出しています。

まずは、これが1万を超えるといいなあとこっそり思っています。

毎日の処方が100あって、一ヶ月で2500程度。それが10店舗あれば25000件です。情報を無碍に廃棄するよりも、共有して財産とした方は薬剤師は次のステージに行ける気がするのですが、個人情報保護法等で難しいのかもしれませんね。

 

処方例データベースも4割がた完成してきましたので、徐々に登録内容等々の規約なども作らなければなりません。Openβなども経由してから、公開しようと思います。

薬剤師のみならず、看護師や医師にも活用していただけるwebサイトになればいいなと思います。

f:id:MC753:20170719213713g:plain

 

明日から

学会出張のため5日ほど更新が止まります。

 

欲しい機能などありましたら、コメントもしくはTwitterの方でご意見いただければ幸いです。