Database †
- 次の2つの表が必要
- アカウント名からパスワードをひける表
- アカウント名からグループをひける表
- まぁこんな感じ (Postgresql)
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE TABLE user_tbl (
id bigserial primary key,
account varchar(255) unique not null,
password varchar(255) not null
);
CREATE TABLE group_tbl (
id bigserial primary key,
user_id bigint references user_tbl (id),
group_name varchar(255) not null
);
INSERT INTO user_tbl (account, password) VALUES ('ichiro', encode(digest('password','sha256'),'hex'));
INSERT INTO user_tbl (account, password) VALUES ('jiro' , encode(digest('password','sha256'),'hex'));
INSERT INTO group_tbl (user_id, group_name) SELECT id,'admin' FROM user_tbl WHERE account='ichiro';
INSERT INTO group_tbl (user_id, group_name) SELECT id,'user' FROM user_tbl WHERE account='ichiro';
INSERT INTO group_tbl (user_id, group_name) SELECT id,'user' FROM user_tbl WHERE account='jiro';
CREATE VIEW account_group_view AS
SELECT u.account as account, g.group_name FROM user_tbl u, group_tbl g WHERE u.id = g.user_id;
- user_tbl
id | account | password |
1 | ichiro | 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8 |
2 | jiro | 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8 |
- group_tbl
id | user_id | group_name |
1 | 1 | admin |
2 | 1 | user |
3 | 2 | user |
- account_group_view
account | group_name |
ichiro | admin |
ichiro | user |
jiro | user |
- ER図
Glassfish への設定 †
- [Server Config]-[Security]-[Realms] に jdbc レルムを追加する (この名前が Web アプリから指定する名前になる)
項目 | 設定値 | 備考 |
Realm Name | jdbc | glassfish-web.xmlで指定する名前 |
Class Name | com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm | |
JAAS Context | JDBCRealm | "JDBCRealm"にする必要あり |
JNDI | jdbc/postgres | Datasource名 |
User Table | user_tbl | |
User Name Column | account | |
Password Column | password | |
Group Table | account_group_view | |
Group Table User Name Column | account | |
Group Name Column | group_name | |
Password Encryption Algorithm | digest-algorithm | 必須項目。パスワードはハッシュ値で保管する |
Assign Groups | | |
Database User | | connection pool ではなく、直接 JDBC 接続するときに指定する |
Database Password | |
Digest Algorithm | SHA-256 | 今回、パスワードは SHA-256 でハッシュ化することにした。SHA-256は、16進数の文字列 (0-9a-f) でデータベースに格納することにした。encode(digest('password','sha256'),'hex') |
Encoding | Hex |
Charset | UTF-8 | |
- パスワードは、通常ハッシュ値で保管する
- ハッシュは一方向
- SHA256(x) = y 同じ原文 x からは、同じハッシュ値 y が得られる。異なる x から同じハッシュ値 y が得られることは実用上ない
- SHA256-1(y) = x という逆変換を行う写像は作ることができない。brute force (力技) で y から x を求めることは実用上できない
- 量子コンピュータが実用化すれば簡単にできる
Webアプリの設定 †
- web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>Member Only</web-resource-name>
<url-pattern>/member/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>memberRole</role-name>
<role-name>adminRole</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin Only</web-resource-name>
<url-pattern>/secure/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>adminRole</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>jdbc</realm-name>
</login-config>
<security-role>
<role-name>memberRole</role-name>
</security-role>
<security-role>
<role-name>adminRole</role-name>
</security-role>
</web-app>
- memberRole, adminRole を持つユーザは、/member/* を閲覧可能
- adminRole を持つユーザは、/secure/* を閲覧可能
- BASIC 認証で、パスワードや権限は jdbc レルムで解決する
- 末尾のロールの列挙は glassfish では必須 (JavaEE規格ではオプショナル)
- glassfish-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC
"-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN"
"http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
<security-role-mapping>
<role-name>adminRole</role-name>
<group-name>admin</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>memberRole</role-name>
<group-name>user</group-name>
</security-role-mapping>
<session-config>
<cookie-properties>
<property name="cookieMaxAgeSeconds" value="-1">
</property>
</cookie-properties>
</session-config>
<class-loader delegate="true"/>
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class' java code.</description>
</property>
</jsp-config>
</glassfish-web-app>
- DB (account_group_view) で検索したグループ名と、アプリケーションのロール名の読み替え定義
group (DB) | role (App) |
admin | adminRole |
user | memberRole |
実行結果 †
/secure/secure.html にアクセスしようとすると、Basic 認証を求められる。ichiro/password で secure.html を閲覧できる
Java#Glassfish