HTTPリクエストヘッダを付加したい

現案件のWebシステムのユーザ認証がクライアントサイドからサーバサイドに変わる。

現状、ユーザ認証はJavaアプレットを使ったシステムによりクライアント側で行う。認証後のユーザ情報はhiddenで持たせて毎回クライアントから業務システムにPOSTさせている(諸事情によりセッションを使うのはナシ)。

しかし、新認証機構ではリバースプロキシ型SSO(シングル・サインオン)となり、認証後のユーザ情報はHTTPリクエストヘッダに乗って来るので、それを業務システム側で受けとる。後続処理は現行との互換性を保つため、クライアントに落としhiddenに埋め込んでおく。

その対応をしたとして、テストのために認証機構のモックアップが欲しい。

HTTPリクエストヘッダに、てきとーな認証情報を埋め込んでくれるようなプロキシを立てればよい。

思いつくのではRubyWEBrickが適任か? 幸い別プロジェクトでRuby on Railsが開発推進用ポータルサイト作成ツールとして認められているのでRubyは使えるはず。

WEBrickでテスト用サーブレットを書く。標準出力にHTTPヘッダを出力。


require "webrick"

serv = WEBrick::HTTPServer.new(:Port => 8888)

serv.mount_proc("/") do |req, res|
p req.request_line
p req.header
p req.body
res.content_type = "text/plain"
res.body = "OK"
end

trap("INT") do
serv.shutdown
end

serv.start

続けて、とりあえずGETメソッドのときにHTTPヘッダ項目を追加するプロキシサーブレットを作成。
特異クラスで動的にread onlyのインスタンス変数へのアクセサを追加。


require 'webrick'
require 'webrick/httpproxy'
include WEBrick

class MyProxyServer < HTTPProxyServer
def proxy_service(req, res)
class << req
attr_accessor :raw_header
end

if req.request_method == "GET"
req.raw_header = req.raw_header.push("User-Info: HogeHoge\r\n")
p req.raw_header
end
super
end
end
s = MyProxyServer.new(
:BindAddress => '0.0.0.0',
:Port => 8080,
:Logger => WEBrick::Log::new($stderr, WEBrick::Log::DEBUG),
:ProxyContentHandler => nil,
:ProxyVia => true,
:ProxyAddress => '127.0.0.1')

trap('INT') do
s.shutdown
end


s.start

これで両サーブレットを立ち上げ、ブラウザのプロキシ設定をlocalhost:8080に向けて、ブラウザはlocalhost:8888にアクセス。

これでめでたく改ざんできたHTTPヘッダを見られ………ないな。

(ソースを読む)プロキシ側でproxy_serviceが呼ばれる前にリクエストがparseされるのでこの後ヘッダを改ざんしても意味なし。

仕方ないからHTTPProxyServer#runメソッドを丸々コピーして、その中でHTTPRequestのread_headerへ特異メソッドをオーバーライド。


class MyProxyServer < HTTPProxyServer
def run(sock)
while true
res = HTTPResponse.new(@config)
req = HTTPRequest.new(@config)

def req.read_header(socket)
super
@raw_header.push("User-Info: HogeHoge\r\n")
begin
@header = HTTPUtils::parse_header(@raw_header)
rescue => ex
raise HTTPStatus::BadRequest, ex.message
end
end

(後略)

これで所望のヘッダは帰ってきた。よきかなよきかな。