ブログ移転のお知らせ

仕事のほうでよい区切りとなったため、ブログを移転することとしました。
販売管理というよりシステム基盤一般のほうに興味が移ってきたため、ブログタイトルやidがそぐわなくなったということもあります。
こちらのブログにも若干アクセスが残っているようなので残したままにしておきます。
移転先:http://d.hatena.ne.jp/masa_w/

久しぶりの日記更新

すっかり更新が滞っておりました。そろそろ活動を始めたいところですが、実際の販管開発を始める前に、ID統一基盤のようなものについて調べてみたいと思っております。最近、標準化の流れがグッと進んでいるようなので。SAML2.0を標準対応とか実現できていると、嬉しい時代がやってくるのかもしれません。

JRubyからSVFを使ってみる

現在、仕事でSVFによる帳票開発をしていますが、簡単なテストスクリプトを書くためにJRubyを使ってみました。

ちょーてきとーですが、こんな感じです。

test.rb

require 'rubygems'
require 'fastercsv'
require 'kconv'
require 'java'
import 'jp.co.fit.vfreport.SvfrClient'
import 'jp.co.fit.vfreport.SvfrException'

begin
  svf = SvfrClient.new()
  ret = svf.VrInit();
  ret = svf.VrSetPrinter("", "PDF");
  ret = svf.VrSetSpoolFileName2("hoge.pdf");
  ret = svf.VrSetForm("hoge.xml", 4);
  FasterCSV.open("hoge.csv", "r").each_with_index do |row, index|
    if index == 0
      @column_names = row.map {|column_name| column_name.toutf8}
    else
      @column_names.each_with_index do |column_name, i|
        ret = svf.VrsOut(column_name, row[i].toutf8);
      end
      ret = svf.VrEndRecord();
    end
  end
  ret = svf.VrPrint();
  ret = svf.VrQuit();
rescue SvfrException => e 
  puts "errorcode: #{ret}"
  puts e
rescue => e2 
  puts e2
end

hoge.xmlというフォーム定義を使い、hoge.csvというファイルを読み込んで、1行目のヘッダ情報から項目名をマッピングし、hoge.pdfを出力します。

Javaのサンプルコードをそのままrubyに移植するだけなので何も難しいことはありませんが、一点つまずいたのは文字コードです。

SvfrClient#VrsOutなどの引数にファイルから読み込んだ文字列をそのまま渡すと文字化けが発生。調べてみたら、こちらのページに行き当たりました。

8. JRuby から Java へのアクセス
http://www.okisoft.co.jp/esc/ruby/tut-08.html

JRubyのソース自体はutf8にしていましたが、CSVファイルのなかがSJISだったため化けてしまっていたようです。Javaモジュールに文字列を渡すとき、utf8に変換してやることで解決しました。CSVファイルの文字コード自体がutf8ならもちろんこの処理は必要ありません。

多少つまづいたもののなんとかJRubyからSVFで帳票を出力することができました。Javaの資産がそのまま使えるのは、今更ながらとても便利ですね。癖になりそうです。まぁ、今回程度のコードならJavaで書いてもあまり変わらないという話もありまする(- -)

帳票出力ツール検討

正月ボケで何も手をつけられませんでしたが、そろそろ始動です。

帳票について

  • TeX
  • JasperReport

の二つを調べてみました。

TeXは帳票作成だけなら良い感じだったのですが、環境を作るのに少し手間がかかりそうです。自分のPCに入れる分には大したことありませんが、パッケージを導入するユーザーさんの立場からあまり多くのソフトに依存させたくないので断念です。ただ、マニュアル作成には利用したいと思っています。

結局JasperReportで進めていくことになるかと思います。JasperReportはJavaのツールですが、工夫するとJRubyを使わず利用できるようなのでとても手軽です*1。おおまかな手順は
http://wiki.rubyonrails.org/rails/pages/howtointegratejasperreports
の通りでしたが、XmlJasperInterface.classはiReportのバージョンにあわせる必要があるので、常にソースからjavacでコンパイルしてやるものだと考えるべきでしょう。コンパイルの段取りも概ね↑のリンク中にあるとおりです。

それと、iReportで最新のnetbeans版を使うと、libなどのフォルダ構成が異なるため若干戸惑いましたが、探せばすぐに発見できるかと思います。

JasperReportは、xmlの出力に強いRails(ActiveRecord)とは非常に相性が良いとおもいます。Restfulに作っておいて、拡張子pdfに対応させておくのが格好よいのではないでしょうか。

*1:javaの実行環境は必要です

ruby_hankanのパッケージ構成

以下のようなパッケージ構成を考えています。

実線は必須、破線はデータ参照のみの依存関係となります。矢印の方向が依存の向きです。
一目瞭然ですが、必須はマスタ管理のみで、他のパッケージは全て単独利用可能となるように設計するつもりです。各パッケージがAPIをもち、相互に連携するイメージです。企業システムは大きくなるほど継ぎはぎでしょう。必要なところだけ使ってもらえればという目論見です。月次締処理などは各パッケージ内で持つことになります。
まずはマスタ管理ができた段階で公開したいと考えています。

シングルサインオン(Single Sign On)の仕組みとSSOサーバの役割

あまり良く分かっていなかったシングルサインオン(以下SSO)についてのまとめ。
そもそもSSOとは、IT用語辞典によると

ユーザが一度認証を受けるだけで、許可されているすべての機能を利用できるようになるシステム。

のことだ。つまり、

図1のようにアプリが1つの場合には不要である。また

図2のようにアプリが複数でも認証情報(Session)を共有する場合には、SSOサーバは必要ない。各アプリの依存度が高い場合や、負荷分散のための複数プロセス構成のケースではこれで充分。そもそもRailsを使うのならSessionの内容はCookieのなかだし(デフォルトでは)。

独立性の高い各アプリの間で認証情報を共有したい場合にSSOサーバは初めて有効となる。

ここで認証画面を各アプリで持つことも可能であるが、SSOサーバに任せた方が実装の手間も省けるし、セキュリティ的にもパスワードを取得するサーバが一箇所ですむので安全だ。
注意すべきは(というか私がよくわかっていなくてもやもやしていたのは)、認証の処理自体を行うのはSSOサーバのみだが、その認証状態を保持するのはWebアプリとSSOサーバの両方だと言うこと。たとえば、あるWebアプリからSSOサーバを通して認証を行ったとする。

まずSSOサーバは認証状態を保持していなければならない。そうでないと、別のアプリから要求があったときに再度ユーザにパスワードを要求しなきゃいけなくなり、シングルサインオンの要件を満たすことができない。
また、Webアプリ側でも認証状態は保持するべきである。ユーザからの要求ごとにSSOサーバに問い合わせを行うのでは、パフォーマンスが低下するし煩わしい。ここでWebアプリが認証状態を保持するのにはなんら特別な技術を必要としない。最初の問い合わせでSSOサーバからOKが出た段階で、ユーザ向けに自前のSession管理機構で新しいSessionIDを振ってやればよいだけだ。

このSession保持についての仕組みが、下手な記事だとあまりよくわからず書かれているし、良く分かってる人はこんなの当たり前の大前提で話しているしで、概念をつかむのに苦労したところであった。

さて、上記をまとめるとSSOサーバが持つべき主な機能は

  1. Webアプリからの認証状態問い合わせに対する応答機能
  2. ユーザに対する認証機能
  3. Session保持機能
  4. WebアプリからのValidation要求への応答機能

というところ。

また、Webアプリ側がSSOのために新たに実装すべき主な機能は

  1. Webアプリで未認証のユーザについてSSOサーバへ認証状態の問い合わせ機能
  2. WebアプリでもSSOサーバでも認証状態にないユーザからのリクエストをSSOサーバにリダイレクトする機能
  3. SSOサーバから認証を受けてリダイレクトされた際のValidation問い合わせ機能

といったところである。

パッケージとしてSSOをサポートしたい場合、SSOサーバの受け口にあわせなければいけないのだが、私には現在の標準仕様がまだ見えていないので、CASに対応するのかSAMLに対応するのか、あるいはOpenSSOやRubyCAS等の具体的なアプリケーションに対応すればよいのかがさっぱりわからない。全てに対応するのはリソース的に論外だ。

とりあえずruby_hankanでは認証部分の機能を入れ替え可能にしておくにとどめ、具体的な対応は後回しにしたいと思います。

(2008/12/19 追記)
上記の説明はエージェント型の仕組みを想定しています。

エージェント型の仕組みを実現するためには、Webアプリ側でSSOエージェントモジュールを組み込む必要があります。SSOサーバとSSOエージェントはセットとなって初めて機能します。RubyアプリからSSOサーバを利用するためには、Ruby用のSSOエージェントモジュールが提供されている必要があります。
他のサイトさんの説明図を見ると、本稿で「SSOサーバ」と表現しているものは単に「認証サーバ」と表記されているケースが多いようです。それでも間違いではないと思うのですが、上で書いたとおりSessionの保持やVailidation機能を持つ必要があるものを単に「認証サーバ」と呼ぶのは個人的には違和感があります。図にすると

と言うイメージです。