「ユーザー認証」の編集履歴(バックアップ)一覧はこちら
「ユーザー認証」(2009/03/10 (火) 23:56:58) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
*&bold(){セッションを使ったカスタム認証}
-ユーザー名とパスワードはHTMLページ上のフォームを使う
-ユーザー管理はデータベースを利用する
-送られてきたユーザー名とパスワードでデータベースを検索して認証する
-認証が通った場合はセッションに記録する
-保護されているページではセッションの有無をチェックする
-ログアウト機能を付ける
認証が行われているかどうかはセッションを使い、「login」データがあるかどうかをチェックする。
HttpSession session = request.getSession(false);
if (session == null){
/* まだ認証されていない */
session = request.getSession(true);
response.sendRedirect("/auth/Login");
}else{
Object loginCheck = session.getAttribute("login");
if (loginCheck == null){
/* まだ認証されていない */
response.sendRedirect("/auth/Login");
}
}
ログイン画面に飛ばした後で、本来アクセスしたかったURLへ移動させるため、どのサーブレットに対してアクセスしようとしていたのかを保存しておく必要がある。本来アクセスしようとしたURLを取得したらセッションの「target」に保存する。
String target = request.getRequestURL();
session.setAttribute("target", target);
|URL|http://localhost:8080/auth/CustomAuth1|
|アプリケーション配置場所|c:\servlet-sample\auth\|
|web.xmlファイル|c:\servlet-sample\auth\WEB-INF\web.xml|
|コンテキストファイル|C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\Catalina\localhost\auth.xml|
*&bold(){JDBCドライバの取得(MySQL用)}
※2009.03.01時点でのバージョンは5.1.7
以下の順でダウンロードする。
+ここにアクセス http://dev.mysql.com/downloads/
+Drivers and ConnectorsのMySQL Connector/J — for connecting to MySQL from Javaの「MySQL Connector/J 5.1」
+Source and Binaries (zip)の「Pick a mirror」
+New Usersの「Proceed」
+画面下部の「No thanks, just take me to the downloads!」
+好きなミラーサイトの「HTTP」
+適当な場所にダウンロード
-インストール
+ダウンロードしたファイルを解凍(mysql-connector-java-5.1.7.zip)
+解凍したフォルダ内のmysql-connector-java-5.1.7-bin.jarをTomcatをインストールしたフォルダ\common\lib\にコピーする。
*&bold(){JDBCドライバのロード}
MySQLの場合は次のように行う。
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
}catch (ClassNotFoundException e){
}catch (Exception e){
}
|URL|http://localhost:8080/database/databasetest|
|アプリケーション配置場所|c:\servlet-sample\database\|
|web.xmlファイル|c:\servlet-sample\database\WEB-INF\web.xml|
|コンテキストファイル|C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\Catalina\localhost\database.xml|
*&bold(){データベースへの接続と切断}
データベースへの接続を確立するには「DriverManager」クラスで用意されている"getConnection"メソッドを使う。
引数には接続するデータベースを表すURLと接続用のユーザー名とパスワードを指定する。
MySQLの場合、URLの形式は次のようになる。
jdbc:mysql://(サーバ名)/(データベース名)
例えばローカルホストにある「jdbctestdb」というデータベースに接続する場合は次のようになる。
jdbc:mysql://localhost/jdbctestdb
実際の使用例
Connection conn = null;
String url = "jdbc:mysql://localhost/jdbctestdb";
String user = "testuser";
String password = "testpass";
try{
conn = DriverManager.getConnection(url, user, password);
// データベースに対する処理
}catch (SQLException e){
}
-データベースの切断
いったん接続した後に切断する場合には、接続の際に取得したConnectionインターフェースのオブジェクトに対して、"close"メソッドを使う。
"close"メソッドは何か問題が発生した際に忘れずに行うためにも、次のように"finally"節を使って記述する。
Connection conn = null;
String url = "jdbc:mysql://localhost/jdbctestdb";
String user = "testuser";
String password = "testpass";
try{
conn = DriverManager.getConnection(url, user, password);
// データベースに対する処理
}catch (SQLException e){
// 例外処理
}finally{
try{
if (conn != null){
conn.close();
}
}catch (SQLException e){
// 例外処理
}
}
*&bold(){データベースの用意}
データベース名は「jdbctestdb」とする。
+MySQLへ接続する: mysql -u root -p
+パスワード応答
+データベースを作成する: create database jdbctestdb;
+テスト用データベースに接続する: use jdbctestdb
+テーブルを作成する: create table kabukatable(code int, company varchar(32), primary key(code) );
+ユーザの追加、権限設定: grant select,insert,update,delete on jdbctestdb.* to 'testuser'@'localhost' identified by 'testpass';
+データを追加する: 下記参照
+データを確認する: select * from kabukatable;
&u(){データを追加する}
※コマンドプロンプトからINSERTしようとした場合、「ERROR 1366 (HY000): Incorrect string value: '\x83r\x83b\x83N...' for column 'com
pany' at row 1」というエラーが発生し追加できない。これはどうやらMySQLインストール時に文字コードをutf-8にしたからの模様。正しい対処かどうかはわからないが、以下のSETコマンドを実行することでINSERTができるようになる。別セッションでSELECTしたりする場合は、毎回このSETを実行しないと文字化けする。
SET character_set_client = sjis;
SET character_set_connection = utf8;
SET character_set_results = sjis;
insert into kabukatable values
(3048,'ビックカメラ'),
(4689,'ヤフー'),
(4755,'RAKUTEN'),
(9984,'SoftBank');
*&bold(){データベース接続テスト}
|URL|http://localhost:8080/database/databasetest1|
*&bold(){データの取得(SELECT)}
-ステートメントを作成する
Connection」インターフェースで定義されている"createStatement"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
-問い合わせの実行
「Statement」インターフェースで用意されている"executeQuery"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "SELECT * FROM kabukatable";
ResultSet rs = stmt.executeQuery(sql);
-結果の取得
カーソルを動かすには「ResultSet」インターフェースで定義されている"next"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "SELECT * FROM kabukatable";
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()){
/* 行からデータを取得 */
int code = rs.getInt("code");
String company = rs.getString("company");
}
データ型毎の値取得メソッド一覧(一部)
boolean getBoolean(String columnName)
byte getByte(String columnName)
Date getDate(String columnName)
double getDouble(String columnName)
int getInt(String columnName)
long getLong(String columnName)
Timestamp getTimestamp(String columnName)
-リソースの開放
使わなくなった「ResultSet」オブジェクトは"close"メソッドを使ってリソースを開放する。
また、「Statement」オブジェクトもに"close"メソッドを使ってリソースを開放する。
rs.close();
stmt.close();
|URL|http://localhost:8080/database/databasetest2|
*&bold(){データの更新(UPDATE)}
「Statement」インターフェースで用意されている"executeUpdate"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "update kabukatable set company='楽天(株)' where code = 4755";
int num = stmt.executeUpdate(sql);
|URL|http://localhost:8080/database/databasetest3|
*&bold(){データの追加(INSERT)}
「Statement」インターフェースで用意されている"executeUpdate"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "insert into kabukatable (code, company) values (2491, 'バリューコマース')";
int num = stmt.executeUpdate(sql);
*&bold(){データの削除(DELETE)}
「Statement」インターフェースで用意されている"executeUpdate"メソッドを使う。
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "delete from kabukatable where id = 4755";
int num = stmt.executeUpdate(sql);
*&bold(){prepareStatementの使用}
「Connection」インターフェースで定義されている"prepareStatement"メソッドを使う。
パラメータとして後から指定する部分には、実際の値を記述する替わりに「?」を記述したSQL文を作成し、そのSQLを元にプリペアドステートメントを作成する。
String sql = "insert into kabukatable (code, company) values (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
この例では実際に挿入する値を記述箇所に「?」を使っている。2箇所使っているので、後からパラメータを2つ指定する必要がある。
-パラメータへ値の設定
「PreparedStatement」インターフェースで用意されている「setInt」メソッドを使う。
パラメータの数だけメソッドを実行する。パラメータはSQL文中に記述された「?」を先頭から順番に1,2,3、・・・と順番に番号が割り当てられる。1番目のメソッドにはパラメータの番号を指定し、2番目の引数にパラメータに設定したい値を記述する。
String sql = "insert into kabukatable (code, company) values (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, 4755);
pstmt.setString(2, "楽天(株)");
パラメータに値を設定するには設定する値のデータ型毎に別々のメソッドが用意されてる。(一部)
|メソッド|説明|
|void setString(int parameterIndex, String x)|String 値に設定します。|
|void setInt(int parameterIndex, int x)|int 値に設定します。|
|void setLong(int parameterIndex, long x)|long 値に設定します。|
|void setByte(int parameterIndex, byte x)|バイト配列に設定します。|
|void setFloat(int parameterIndex, float x)|float 値に設定します。|
|void setDouble(int parameterIndex, double x)|double 値に設定します。|
|void setDate(int parameterIndex, Date x)|java.sql.Date 値に設定します。|
|void setTime(int parameterIndex, Time x)|java.sql.Time 値に設定します。|
|void setBoolean(int parameterIndex, boolean x)|boolean 値に設定します。|
|void setTimestamp(int parameterIndex, Timestamp x)|java.sql.Timestamp 値に設定します。|
-プリペアドステートメントの実行
「PreparedStatement」インターフェースにはSELECTなどのクエリーの結果を取得する場合に使う「executeQuery」メソッドと、INSERTやUPDATEなどの結果が返されない場合に使う「executeUpdate」メソッドがある。この使い方は「Statement」の場合と同じ。
conn = DriverManager.getConnection(url, user, password);
String sql = "insert into kabukatable (code, company) values (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, 4755);
pstmt.setString(2, "楽天(株)");
int num = pstmt.executeUpdate();
-パラメータのクリア
プリペアドステートメントを複数回続けて実行する場合、値が変更されないパラメータについては改めて設定する必要はない。
次の例では1番目のパラメータは変更が無く、2回目に実行する時には2番目のパラメータだけを設定する。
String sql = "insert into kabukatable (basho, company) values (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, "東証");
pstmt.setString(2, "ドコモ");
int num = pstmt.executeUpdate();
pstmt.setString(2, "KDDI");
num = pstmt.executeUpdate();
現在設定されているパラメータを全て一度クリアしたい場合には「PreparedStatement」インターフェースで用意されている「clearParameters」メソッドを使う。
|URL|http://localhost:8080/database/databasetest6|
*&bold(){セッションを使ったカスタム認証}
-ユーザー名とパスワードはHTMLページ上のフォームを使う
-ユーザー管理はデータベースを利用する
-送られてきたユーザー名とパスワードでデータベースを検索して認証する
-認証が通った場合はセッションに記録する
-保護されているページではセッションの有無をチェックする
-ログアウト機能を付ける
認証が行われているかどうかはセッションを使い、「login」データがあるかどうかをチェックする。
HttpSession session = request.getSession(false);
if (session == null){
/* まだ認証されていない */
session = request.getSession(true);
response.sendRedirect("/auth/Login");
}else{
Object loginCheck = session.getAttribute("login");
if (loginCheck == null){
/* まだ認証されていない */
response.sendRedirect("/auth/Login");
}
}
ログイン画面に飛ばした後で、本来アクセスしたかったURLへ移動させるため、どのサーブレットに対してアクセスしようとしていたのかを保存しておく必要がある。本来アクセスしようとしたURLを取得したらセッションの「target」に保存する。
String target = request.getRequestURL();
session.setAttribute("target", target);
|URL|http://localhost:8080/auth/CustomAuth1|
|アプリケーション配置場所|c:\servlet-sample\auth\|
|web.xmlファイル|c:\servlet-sample\auth\WEB-INF\web.xml|
|コンテキストファイル|C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\Catalina\localhost\auth.xml|
*&bold(){セッションを使ったカスタム認証(ログアウト処理)}
ログアウトの処理は、セッションを無効にすればいいだけ。
HttpSession session = request.getSession(true);
session.invalidate();
response.sendRedirect("/auth/Login");