« 滑走日数5日目(ダイナランド) | トップページ | Baby Care Report ~画伯誕生?~ »

2009年2月15日 (日)

[VB.NET]「Atom API」を実装してのデータ送信

Webサービスとやり取りを行う「Atom API」をVB.NETで実装してみました。

この場合、キモとなるのは「WSSE認証」だと思うのですが、「WSSE認証」は要するにワンタイムパスワードみたいなものなので規格の内容を把握してればそれほど難しくは無いよーです。
(ちなみに「WSSE認証」は「SOAP」でも使われてます)

以下のコードは「WSSE認証」用のヘッダを付加してXMLドキュメントをPOSTしています。

'--------------------------------------
' ATOMを利用してXMLドキュメントを送信します
'--------------------------------------
Private Sub postXML()

    Dim strURL As String = ""
    Dim strResStr As String = ""

    'エンドポイントの設定
    strURL = "http://hogehoge.jp/atom/hoehogeService"

    'WSSE認証文字列の生成
    Dim wsseHeader As String = createWSSE("ID", "Password")

    'リクエスト用XMLの作成
    '内容をHTMLエンコードしないとXMLとして不正となる
    Dim strPostData As String = "<?xml version='1.0' encoding='utf-8'?>" & _
                                "<entry xmlns='http://purl.org/atom/ns#'>" & _
                                    "<title>" & Web.HttpUtility.HtmlEncode("題名") & "</title>" & _
                                    "<summary>" & Web.HttpUtility.HtmlEncode("本文") & "</summary>" & _
                                "</entry>"
    Dim byteData As Byte() = System.Text.Encoding.UTF8.GetBytes(strPostData)

    '送信用設定(XMLとして送信)
    Dim webreq As Net.HttpWebRequest = DirectCast(System.Net.WebRequest.Create(strURL), System.Net.HttpWebRequest)
    With webreq
        .Headers.Add("X-WSSE", wsseHeader)
        .Method = "POST"
        .ContentType = "application/atom+xml"
        .ContentLength = byteData.Length
    End With

    '接続&XMLドキュメントを送信
    Using reqStream As IO.Stream = webreq.GetRequestStream()
        reqStream.Write(byteData, 0, byteData.Length)
    End Using

    '送信結果の取得
    Using webres As Net.HttpWebResponse = webreq.GetResponse
        'ヘッダの内容を取得
        With webres
            For i = 0 To .Headers.Count - 1
                Debug.Print(.Headers.Keys(i) & ":" & .Headers(i))
            Next i
        End With

        '返信内容を取得
        Using resStream As IO.Stream = webres.GetResponseStream()
            Using sr As New IO.StreamReader(resStream, System.Text.Encoding.GetEncoding("UTF-8"))
                Debug.Print(sr.ReadToEnd())
            End Using
        End Using
    End Using

End Sub

'--------------------------------------
' ATOMのWSSE認証用ヘッダ文字列を生成します
'--------------------------------------
Private Function createWSSE(ByVal strID As String, ByVal strPw As String) As String

    createWSSE = ""

    ' nonce(HTTPリクエスト毎に生成するセキュリティ・トークン=ランダムな文字)の作成
    Dim nonce As String = RandomStringClass.CreateRandomString(20)

    ' Created(Nonceが作成された日時をISO-8601で表記)
    Dim created As String = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ssZ")

    ' PasswordDigest(Nonce+Created+パスワードをSHA1でダイジェスト化)
    Dim sha1 As New Security.Cryptography.SHA1Managed()
    Dim pwdigest As Byte() = sha1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(nonce & created & strPw))

    ' WSSE認証用のヘッダを作成(PasswordDigestとnonceはBase64でエンコード)
    Dim format As String = "UsernameToken Username=""{0}"", PasswordDigest=""{1}"", Nonce=""{2}"", Created=""{3}"""
    createWSSE = String.Format(format, strID, Convert.ToBase64String(pwdigest), Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(nonce)), created)

End Function

基本的にデータ送信はHttpWebRequestクラスを使ったオーソドックスなデータ送信です。
それにWSSE認証用のヘッダが追加されているって事になります。

WSSE認証用の各パラメータについては、Webで色々調べるて頂くとして、HTTPリクエスト毎に生成するセキュリティトークンである「nonce」だけちょっと触れます。

今回のサンプルの場合、nonceは「暗号乱数ジェネレータを使った厳密にランダムな文字列の生成」を利用してランダムに生成された文字列としていますが、本来は、8bitのByte値であり、0~9・A~Z・a~zの文字に限定されません。
また、サイズについても本来は任意のバイト数となっているよーです。

ちなみにパスワードを含んでいるPasswordDigestはハッシュ値なので、要求を受け取ったサーバ側で認証する際にサーバ側のDBに格納されているパスワードは平文に変換できるよーになってないと比較する事ができなかったりします。
もし、サーバ側DBに格納されているパスワードがハッシュ値しか無い場合は、クライアントはサーバ側と同じ方式でパスワードのハッシュ値を得てPasswordDigestにセットする事になるはずです。
クライアント側もたまたま同じ方式でハッシュ値を保存してれば、サーバ・クライアントイ共に平文のパスワードを得る方法が存在しないので脆弱性を突かれた場合を考えるとセキュリティ的に良いんですが、オープンなAPIとなった場合、上記理由から結果的にパスワードの保存方法の手の内を晒すことになったりします・・・。

|

« 滑走日数5日目(ダイナランド) | トップページ | Baby Care Report ~画伯誕生?~ »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/26493/28090659

この記事へのトラックバック一覧です: [VB.NET]「Atom API」を実装してのデータ送信:

« 滑走日数5日目(ダイナランド) | トップページ | Baby Care Report ~画伯誕生?~ »