JBoss5でユーザー認証(BASIC認証・DIGEST認証・FORM認証)を行う

WEBアプリでサーバーにユーザ認証をまかせるとき、TomcatJBossとではサーバー側の設定が少し異なる。

JBossのバージョン情報:
Name: JBoss SOA-P 5 (development)
Version: 5.3.0.GA
Description: JBoss Enterprise SOA Platform



設定すべきファイルは以下の4つ

JBoss側の設定ファイル
1.sample-ds.xml(sample部は任意)
 datasouce(例えば、データベース)への接続方法を記述
2.login-config.xml
 1.のdatasourceを利用した認証方法を記述
WEBアプリ側の設定ファイル
3.jboss-web.xml
 2.との接続を記述
4.web.xml
 認証方法を記述


JBoss側の設定

1.sample-ds.xml(sample部は任意)
$JBOSS_HOME/server/development/deploysample-ds.xml を作成

<?xml version="1.0" encoding="UTF-8"?>

<!-- $Id: mysql-ds.xml 63175 2007-05-21 16:26:06Z rrajesh $ -->
<!--  Datasource config for MySQL using 3.0.9 available from:
http://www.mysql.com/downloads/api-jdbc-stable.html
-->

<datasources>
  <local-tx-datasource>
    <jndi-name>sampleDS</jndi-name>
    <connection-url>jdbc:mysql://mysqldb:3306/sample?autoReconnect=true</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>user</user-name>
    <password>pass</password>
    <metadata>
       <type-mapping>mySQL</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>

jdbc:mysql://mysqldb:3306/sample?autoReconnect=true」はデータベースのurl



2.login-config.xml
$JBOSS_HOME/server/default/conf/login-config.xml に追記

<application-policy name = "sampleAuth">
  <authentication>
    <login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule"
      flag = "required">
      <module-option name = "dsJndiName">java:/sampleDS</module-option>
      <module-option name="principalsQuery">
        select password from user_info where user_name=?
      </module-option>
      <module-option name="rolesQuery">
	 select role , 'Roles' from user_info where user_name=?
      </module-option>
    </login-module>
  </authentication>
</application-policy>

user,passのデータベース作成については下部の参考2を参照(参考2中のrolesQueryの文法に誤りがあるので注意)
テーブルの構成に応じてクエリは変更が必要


WEBアプリ側の設定

3.jboss-web.xml
/WEB-INF/jboss-web.xml を作成

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
    <!-- Use the JaasSecurityMgr other security domain for authentication
      and authorization of secured web content.
     -->
    <security-domain>java:/jaas/sampleAuth</security-domain>
</jboss-web>

sampleAuthは2.で設定したJNDI

4.web.xml
/WEB-INF/web.xml に追記

<security-constraint>
  <web-resource-collection>
    <web-resource-name>Protected Area</web-resource-name>
    <url-pattern>/</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>user</role-name>
  </auth-constraint>
</security-constraint>


<login-config>
  <auth-method>FORM</auth-method>
  <realm-name>User Form Auth</realm-name>
  <form-login-config>
    <form-login-page>/login.html</form-login-page>
    <form-error-page>/error.html</form-error-page>
  </form-login-config>
</login-config>

<security-role>
  <role-name>user</role-name>
</security-role>

他の認証方式(BASIC認証・DIGEST認証)を利用したい時はauth-methodを変更



参考にしたサイト:
参考1https://access.redhat.com/documentation/ja-JP/JBoss_Enterprise_Application_Platform/5/html/Security_Guide/ch12.html
参考2JBoss各種Tips

pythonによる強調フィルタリング手法GroupLensの実装

レコメンドシステム構築の為、まずは定番のGroupLensの実装を行った。

python(crab)でもR(recommenderlab)でもライブラリはあるようだが、
さして複雑なアルゴリズムではないので、使いこなすより実装した方が早いと判断し、
pythonによる実装を試みた。

アルゴリズムは参考1のP50-56を利用している。
例題も同著の以下のデータを利用。

f:id:Tug-uca:20150517162841j:plain

# -*- coding: utf-8 -*-
import numpy as np

def pearson(e1,e2):
    #入力されたリストのうち、どちらともゼロでない要素のみの相関係数を算出
    te1=[]
    te2=[]
    tmp=np.array(e1)*np.array(e2)
    for i in range(len(tmp)):
        if tmp[i]!=0:
            te1.append(e1[i])
            te2.append(e2[i])
    if len(te1)==1:
        return 0
    return np.corrcoef(te1,te2)[0,1]

def average(e):
    #入力されたリストのうち、ゼロでない要素のみの平均を算出
    n = sum(e)
    d = len([x for x in e if x!=0])
    return n/d

def evaluate(a,y,data,arr):
    #評価推定値を算出
    aveA = average(data[a])
    d=0
    n=0
    for i in range(len(data)):
        if a!=i and data[i][y]!=0:#a自身と、yの評価値がないユーザを除く
            d+=abs(arr[a][i])
            # tmp=np.array(data[a])*np.array(data[i])
            # tmp2 = [0 for i in range(len(data[i]))]
            # for k in range(len(tmp)):
            #     if tmp[k]!=0:
            #         tmp2[k]=data[i][k]
            # n+=arr[a][i]*(data[i][y]-average(tmp2))
            
            #共通要素以外も含めた平均を利用、上部コメントアウト部分は共通要素を除いた平均を利用した場合
            n+=arr[a][i]*(data[i][y]-average(data[i]))
    return aveA+n/d


data = [[0 for i in range(4)] for j in range(4)]
arr = [[0 for i in range(4)] for j in range(4)]
eva = [[0 for i in range(4)] for j in range(4)]

# データの入力
data[0]= [1,3,0,3]
data[1]= [0,1,3,0]
data[2]= [2,1,3,1]
data[3]= [1,3,2,0]




# ユーザー間の類似度計算
for key in range(len(data)):
    base_customers = data[key]
    for key2 in range(len(data)):
        if key == key2:
            continue
        target_customers = data[key2]
        j = pearson(base_customers, target_customers)
        arr[key][key2] = j

#ユーザ・商品ごとの評価値推定
for i in range(len(data)):
    for j in range(len(data[i])):
        eva[i][j] = evaluate(i,j,data,arr)

# ユーザー間の類似度
print(' \t  1 \t  2 \t  3 \t  4 ')
print('1\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(arr[0][0], arr[0][1], arr[0][2], arr[0][3]))
print('2\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(arr[1][0], arr[1][1], arr[1][2], arr[1][3]))
print('3\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(arr[2][0], arr[2][1], arr[2][2], arr[2][3]))
print('4\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(arr[3][0], arr[3][1], arr[3][2], arr[3][3]))

#ユーザ・商品ごとの評価値推定値
print(' \t  1 \t  2 \t  3 \t  4 ')
print('1\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(eva[0][0], eva[0][1], eva[0][2], eva[0][3]))
print('2\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(eva[1][0], eva[1][1], eva[1][2], eva[1][3]))
print('3\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(eva[2][0], eva[2][1], eva[2][2], eva[2][3]))
print('4\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(eva[3][0], eva[3][1], eva[3][2], eva[3][3]))

  • 実行結果
 	  1 	  2 	  3 	  4 
1	0.00	0.00	-1.00	1.00
2	0.00	0.00	1.00	-1.00
3	-1.00	1.00	0.00	-0.50
4	1.00	-1.00	-0.50	0.00
 	  1 	  2 	  3 	  4 
1	1.71	3.21	1.71	3.08
2	2.62	1.12	2.62	1.25
3	2.97	0.88	2.42	1.08
4	1.03	2.82	0.92	2.69

以上。



参考1:推薦システムのアルゴリズム
www.kamishima.net/archive/recsysdoc.pdf

消費者来店行動モデルのパラメータ推定(poisson分布)

ここでは実店舗が存在し、商品を販売する小売業を想定している。

このとき消費者の来店間隔はポアソン分布に従うと知られている。(阿部2007)

これは、消費者ごとに毎日一定確率で来店し、それが繰り返されているというモデルである
(来店間隔の最小単位を1日とする。)

「消費者ごと」の一定確率を実績から推定する方法を考えたい。

f:id:Tug-uca:20150109191432j:plain

ポアソン分布のパラメータはλのみであり、これを推定すればよい。

f:id:Tug-uca:20150109191449j:plain

これは期間中の平均来店実績に他ならない。


つまり、来店日数/観測日数 で算出できる

参考:
阿部誠(2007)消費者行動理論にもとづいた個人レベルの RF 分析:階層ベイズによる Pareto/NBD モデルの改良,MMRC Discussion Paper No. 18

既存プロジェクトをSourceTreeでbitbucketにgitリポジトリを作成する手順

方法はいろいろあると思うが、ここではすべてをSourceTree上で行う手順を記述する。


1.既存プロジェクタ(フォルダ)をSouceTreeに読み込み
f:id:Tug-uca:20141231164638j:plain



2.管理対象ファイルを選択し、marterブランチを作成
f:id:Tug-uca:20141231164702j:plain


3.コミットする
f:id:Tug-uca:20141231175905j:plain


4.bitbucket上のリポジトリを作成
f:id:Tug-uca:20141231180057j:plain


5.ローカルのリポジトリにリモートのリポジトリを追加
f:id:Tug-uca:20141231175924j:plain


URL/パス:https://[アカウント名]@bitbucket.org/[アカウント名]/[リポジトリ名].git
f:id:Tug-uca:20141231180117j:plain



6.ローカルのリポジトリにリモートのリポジトリにプッシュ
f:id:Tug-uca:20141231164703j:plain


以上。

Apache Commons VFSでusername,passwordに利用禁止文字を使う方法

String  hostName = "US456564" ; 
String username  = "sftpuser@Location";
String password = "Test!@#$%^&*()[]:;";
String  localFilePath = "home57556";

FileObject remoteFile = manager.resolveFile(					createConnectionString(hostName, username, password, remoteFilePath, fileName),					createDefaultOptions());

Apache Commons VFSを利用する際、usernameやpasswordに@等の文字を使うと以下のようなエラーが出てftpにアクセスすることができない。

Caused by: org.apache.commons.vfs2.FileSystemException: Invalid absolute URI "sftp://sftpuser@Location:***@US456564/home57556".


これは内部的には以下のようにアクセスしているためである。

manager.resolveFile("sftp://sftpuser@Location:Test!@#$%^&*()[]:;@US456564/home57556");


この時は、使用できない文字を%○○のようにエンコードしたものを入力するとアクセスができる。

manager.resolveFile("sftp://sftpuser%40Location:Test!%40%23%24%25%5E%26*%5B%5D%3A%3B@US456564/home57556");

eclipseで特定ファイルを除外してwarを作成する(antを利用)

warファイルを作成するにあたって、プロジェクト内のライブラリやgitのリポジトリも一緒にまとめてしまうので、必要以上にサイズが大きくなっていたのでapache-antを使って特定ファイルを除外してwarを作成する方法を調べた。

1.apache-antのインストール

http://ant.apache.org/にアクセスし、zip版をダウンロードする。
ダウンロードしたら任意のフォルダ(今回はProgram Files内)に展開する。
以下の環境変数を追加する。
ANT_HOME C:\Program Files\apache-ant-1.9.4
PATH C:\Program Files\apache-ant-1.9.4\bin

C:\> ant -version
Apache Ant(TM) version 1.9.4 compiled on April 29 2014

上記のようになればインストール成功

2.build.xmlの作成

プロジェクト直下に以下の内容のbuild.xmlを作成する。
このとき、のように、除外したいファイル・フォルダを指定する。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
              	
		 <project basedir="." default="dist" name="">

              	  <!-- warファイルの設定 -->
              	  <property name="war.home" value="." />
              	  <property name="web-app.name" value="appName" />

              	  <!-- jarタスクによってwarファイルを作成 -->
              	  <target name="dist" >
              	    <war destfile="${war.home}/${web-app.name}.war"
              	           webxml="${war.home}/WEB-INF/web.xml">
              	      <fileset dir="${war.home}" excludes="**/web.xml,**/WEB-INF/lib/**,${web-app.name}.war" />
              	    </war>
              	  </target>
</project>

3.warファイルの作成

eclipse内で、build.xmlを右クリック → 実行 → Antビルド
コンソール上で

BUILD SUCCESSFUL
Total time: 985 milliseconds

のような表記が出れば、成功。
warファイルがプロジェクト内直下に作成されている。

pythonでwebアプリ(pythonインストールからDB接続まで)

pythonでwebアプリを作れる環境を作りたくて、bottle、mysql-connector-pythonを試してみた。
フレームワークは他にも有力なのがあるようでまだbottleでいくかは未決定。
OS:windows8 64bit

https://www.python.org/downloads/
最新版のpython3.4.1をダウンロードして実行。python2に対し後方互換性がないようだが、
どんどん対応するライブラリが増えており、使いたいライブラリはすべてpython3に対応しているようなので、python3で決定。
インストールが完了したらc:\python34とc:\python\Scriptsへのパスを通しておく。

  • pipのインストール

使ったことがないので便利さがわからないのだが、いろんなところにpythonとセットで書いてあるのでとりあえずインストールする。
setuptoolsから(https://pypi.python.org/pypi/setuptools)
環境に応じたez_setup.pyをダウンロードする。

python ez_setup.py
easy_install pip

これで完了。

...もっと簡単にpipを入れる方法もある模様
http://qiita.com/who_you_me/items/831d62f396e6d66dda66

  • エディタのインストール

何でもよいのだが評判が良いのでPyCharm Community Editionをインストール
http://www.jetbrains.com/pycharm/download/
日本語化されてないのが難点

  • bottleのインストールと実行
pip install bottle

インストールしたら公式のチュートリアルに従って実行してみる
http://bottlepy.org/docs/dev/tutorial.html

from bottle import route, run

@route('/hello')
def hello():
    return "Hello World!"

run(host='localhost', port=8080, debug=True)

とりあえずこれでサーバーが立つのでhttp://localhost:8080/helloへアクセスして確認する。
サーバーはgunicornを使うとよいとのこと

DBは既存のmysqlを使いたいのでドライバが必要。
ドライバはいろいろありすぎるよう(参考:http://www.sakito.com/2012/10/python-mysql.html
これといった性能要件もないのでmysql-connecter-pythonを使ってみることにした。
インストール

pip install mysql-connector-python

もし、--allow-externalをつけなさい、というようなエラーが出たら

pip install --allow-external mysql-connector-python mysql-connector-python

DBの方にはあらかじめテーブルを用意しておく。
以下は、DB:testのtable:table1から全データを持ってきて表示するサンプル

import mysql.connector
connect = mysql.connector.connect(db="test", host="localhost", port=3306, user="****", passwd="****")

cur=connect.cursor()
cur.execute('select * from table1')
rows = cur.fetchall()
for row in rows:
    print(row)

cur.close()
connect.close()
  • まとめ

とりあえず最低限動かすための準備はできた。
残りはやりたいことに対して必要な機能(テンプレートとかlogとか)の確認と、
そもそものフレームワークの選定。
他の候補としては実績が多いDjangoかBottleと同じく軽量なFlaskあたりを見てみる予定。