none
テスト環境では動くが、サーバーでは動かない RRS feed

  • 質問

  • テスト環境では動くが、サーバーでは動かない

    いつもお世話になっております。

    一点、タイトルの件で、アドバイスをいただきたく、質問させていただきます。

    現在、Googleコンタクトと連携したwebアプリを作成していまして、ローカルでの動作は意図どおりなのですが、サーバーにアップするとエラーが返されてしまいます。

    エラーの内容は、Invalid credentials なので、おそらくセキュリティーで引っかかってしまっているのだと思うのですが、原因がわかりません。


    別の方が、過去、Google Calender API の件で、MSDNに投稿した際に、
    『Googleが提供しているAPIの件に関しては、ここでは解答が付きにくいのでは?』
    といったご指摘があったようですが、今回はローカルとサーバー上での環境の差異が影響していると思い、こちらにも質問させていただきました。
    (ちなみに、Googleのフォーラムにも質問を投稿しています。が、フォーラムをイ見ていただければ一目瞭然ですが、こちらも回答が期待できる状況ではありません。…解答が付かない質問が大量に残っていたり、エンジニアのリクルート記事が大量にあったりなど)


    開発環境やサーバーの環境は、
    Local : Windows 7 + Visual web Developer2010 + VWDのテストサーバー(Microsoft .NET Framework バージョン:2.0.50727.3634; ASP.NET バージョン:2.0.50727.3634)
    Server : Windows 2003 R2 SP2 + IIS 6.0(Microsoft .NET Framework Version:2.0.50727.3615; ASP.NET Version:2.0.50727.3618)
    で、.NET のバージョンはわずかに違うものの、基本的には同一のもの考えてよい範囲だと思うので、動作環境の前提は問題ないと考えています。


    .NET library for the Google Data API v3

    を使用していますが、API依存のエラーではないと思うのですが、どなたか原因の予測がつく方がいらっしゃいましたら、ご助言をお願いします。

     

    以下、テスト用のコードです。
    動作としては、入力のGoogle ID・Passのログイン情報をもとに、名前、電話番号のすべて、e-mailアドレスのすべてを取得して、表示させるだけのシンプルなテストコードです。
    ローカル環境では、動作に成功しています。
    エラー発生箇所は、
    Dim gdata As ContactsFeed = gadrs.Query(gaddQuery)
    と、表示され、理由は『Invalid credentials』です。

            Dim gadrs As ContactsService = New ContactsService("AdrsList")
            
            Dim guid As String = gid.Text
            Dim gupw As String = gpw.Text
            gadrs.setUserCredentials(guid, gupw)
                   
            Dim gaddQuery As New ContactsQuery("https://www.google.com/m8/feeds/contacts/" + guid + "/full") '
            Dim gdata As ContactsFeed = gadrs.Query(gaddQuery)
            Dim ckAddLen As Integer = gdata.Entries.Count - 1
            Dim adradr As StringBuilder = New StringBuilder()
            Dim eachData As ContactEntry = New ContactEntry()
            Dim gName As String = Nothing
            Dim gTel As String = Nothing
            
            For I As Integer = 0 To ckAddLen
                eachData = CType(gdata.Entries.Item(I), ContactEntry)
                gName = ""
                If Not eachData.Name Is Nothing Then gName = eachData.Name.FullName
                gTel = ""
                If Not eachData.Phonenumbers.Count = 0 Then
                    Dim tTel As String = Nothing
                    For J As Integer = 0 To eachData.Phonenumbers.Count - 1
                        tTel += eachData.Phonenumbers(J).Value & " / "
                    Next
                    gTel = tTel
                End If
                If Not eachData.Emails.Count = 0 Then
                    Dim tEmail As String = Nothing
                    For J As Integer = 0 To eachData.Emails.Count - 1
                        tEmail += eachData.Emails(J).Address & " # "
                    Next
                    gTel += tEmail
                End If
                adradr.Append(gName)
                adradr.Append(" * ")
                adradr.Append(gTel)
                adradr.Append("<br />")
            Next
            Label1.Text = adradr.ToString

    Server Error in '/' Application.

    Invalid credentials

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: Google.GData.Client.InvalidCredentialsException: Invalid credentials
     
     
    Stack Trace:
    [InvalidCredentialsException: Invalid credentials]
       Google.GData.Client.Utilities.QueryClientLoginToken(GDataCredentials gc, String serviceName, String applicationName, Boolean fUseKeepAlive, IWebProxy proxyServer, Uri clientLoginHandler) +904
       Google.GData.Client.GDataGAuthRequest.QueryAuthToken(GDataCredentials gc) +251
       Google.GData.Client.GDataGAuthRequest.EnsureCredentials() +41
       Google.GData.Client.GDataRequest.EnsureWebRequest() +1091
       Google.GData.Client.GDataGAuthRequest.EnsureWebRequest() +26
       Google.GData.Client.GDataRequest.Execute() +42
       Google.GData.Client.GDataGAuthRequest.Execute(Int32 retryCounter) +480
       Google.GData.Client.GDataGAuthRequest.Execute() +10
       Google.GData.Client.Service.Query(Uri queryUri, DateTime ifModifiedSince, String etag, Int64& contentLength) +193
       Google.GData.Client.Service.Query(FeedQuery feedQuery) +202
       Google.GData.Contacts.ContactsService.Query(GroupsQuery feedQuery) +5
       ASP.marugoto_gtest_aspx.gbtn_Click(Object sender, EventArgs e) in D:\CustomerData\webspaces\webspace_00123456\wwwroot\*******\******\*****.aspx:31
       System.Web.UI.WebControls.Button.OnClick(EventArgs e) +111
       System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +110
       System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
       System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
       System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1565
    

    ぷら

    2012年10月3日 2:49

すべての返信

  • VWD上のサーバーとIISでは実行時のユーザーが異なります。
    テスト環境で実行できて、IISで実行できない、というのはたいていこのユーザーの権限の違いによるものです。
    ライブラリを実行するのにどういった権限が必要なのか、を確認し、その権限をIISの実行時ユーザーに付加するのにどうしたらよいか、という観点から調べてみると解決できるかもしれません。


    あおい情報システム株式会社 小野修司(どっとねっとふぁん)

    2012年10月3日 6:35
  • 小野さんのレスとダブルところがありますが、また、Google
    API は全く知りませんが・・・

    > テスト環境では動くが、サーバーでは動かない

    Web サーバーに必要なライブラリはインストール(dll を bin
    フォルダにコピー)してありますか?

    上記が OK として、テスト環境というのは ASP.NET 開発サーバ
    ーで動かしたのだと思いますが、開発マシンでも IIS で動かす
    とどうなりますか?

    開発サーバーで動いても、IIS で動かないということはよくあ
    る話です。一番大きな違いがワーカープロセスのアクセス権で
    す。

    ASP.NET 開発サーバーと IIS
    http://surferonwww.info/BlogEngine/post/2011/11/18/ASPNET-development-server-and-IIS.aspx

    それが原因かどうかはわかりませんが、とにかく、まずは、開発
    サーバーを使うのは止めて、IIS を使ってください。話はそれか
    らです。(と言っても、自分は ASP.NET 一般の話以外はできな
    いと思いますが)

    2012年10月3日 10:36
  • 小野@どっとねっとふぁん さま
    SurferOnWww さま

    いつもご助言をいただきましてありがとうございます。

    ご指摘いただきましたユーザー権限ですが、実行時にコンパイルエラーが出ていないので、web.config、DLLの配置は適切だと考えています。また、今回は、サーバー側で物理的な書き込みが発生しないので、特に気にしていませんでしたが、勉強不足で申し訳ないのですが、ユーザー権限というのは、読み書き実行以外にも何か存在したりするものなのでしょうか?このあたりの理解が不十分であれば、このあたりの原因追求もしていこうと思います。

     

    今、私が調べた限りで疑っている原因は、ローカルとサーバーで、オブジェクトが若干違う振舞いをすることがないかどうか?です。特に、HTTPリクエストやヘッダーなどです。この辺りは、何かチェックすべき点が思いつくようでしたら助言をいただければ幸いです。

    ちょっと長くなってしまうのですが、以下に、私なりに調べた結果を簡単にまとめました。

    まず、エラーの理由は、サーバーで実行させたときに認証に失敗したときの InvalidCredentialsException がスローされてしまうということです。これは、ローカルでもIDやPassをいい加減に入れた場合は同じ例外がスローされますが、資格情報をハードコーディングしても同じエラーが返されていますので、おそらく、プログラムのオブジェクトが認証に失敗していると考えております。

    その、失敗する原因が、いまいち、サーバー環境なのか?GoogleAPIに対するリクエストが正しく処理されていなくて発生するエラーなのか?この辺りがわからずに困っています。

    ユーザー権限に似ているのかもしれませんが、オブジェクトが生成されるときに、ローカルとサーバーで、保持する値が異なることがあれば、そのあたりにヒントが隠れていそうなのですが、私が調べた限りでは違いがわかりませんでした。

    比較した内容は、プログラム上で
    Dim gadrs As ContactsService = New ContactsService("AdrsList")
    を宣言して、APIに処理を実行するオブジェクトを作成していますので、この辺りのプロパティを調べてみました。

    このオブジェクトはアクセス情報(リクエスト情報)や認証情報を保持するプロパティが存在しています。そして、APIにデータを要求するたびに、このオブジェクトが保持しているアクセス資格でデータを受け取っているのではないかと考えています。今回エラーになるのは、このクエリを実行しようとするときに認証エラーになり、例外がスローされていると考えています。

    なので、このオブジェクトのプロパティに関して、ローカル、サーバーそれぞれ実行時の、プロパティに格納されるすべての値を比較してみました。
    その結果、どちらで実行しても同じ情報が格納されていて、何かが抜け落ちたり足りていないということがなかったので、保持しているデータが同一ということで、ローカル実行時とサーバー実行時の違いが良くわからず、困っています。

    今、一番怪しいと注目している部分は、HTTPリクエスト時のヘッダーの違いの部分です。

    以前、webclient オブジェクトを使ったプログラムを組んだことがあります。これは、あるサイトからHTMLを吸い出して、一部のデータを参照するという内容のものを作ったことがあったのですが、このときに、webclientがデータを取りにいったときと、ブラウザで見たときで、吐き出しているhtmlが違うということがあり、大変困ったことがあります。原因は、相手方のプログラムがUAを参照していたので、ブラウザで表示したときと、webclientがアクセスした場合で違うhtmlが帰ってきていたというものでした。

    今回も、こういった、実行環境の違いでヘッダーの違いやHTTPリクエストの変数が異なっているのではないかとも考えましたが、自力で調べた限りでは原因を突き止められませんでした。

    大変長くなりましたが、こういった考察から、ローカルとサーバーで、私が調べた以外に、何か動作に違いがないか、とか、他にチェックすべき点など、思いつくものがありましたら、ぜひ、ご助言をいただきたいと思います。

    なにとぞよろしくお願いします。


    ぷら

    2012年10月4日 4:34
  • > また、今回は、サーバー側で物理的な書き込みが発生しないので、特に気にしていませんでしたが、勉強不足で申し訳ないのですが、ユーザー権限というのは、読み書き実行以外にも何か存在したりするものなのでしょうか?

    物理的な読み書きが発生しない、というのは利用しているDLLも含めて確実に発生しないのですか?
    この読み書きにはストリームも含めて考える必要があると思います。
    DLL経由でネットワークへのアクセスを行うっているので、ストリームの読み書きは確実に発生していると思いますが。。。
    そのあたりにも問題は発生しないんですかね?

    DLLの作りによっては上記のような、使い手が意図しないかたちでアクセス権に抵触する可能性があるのではないかと思います。


    あおい情報システム株式会社 小野修司(どっとねっとふぁん)

    2012年10月4日 5:18
  • 先のレスで、

    > とにかく、まずは、開発サーバーを使うのは止めて、IIS
    > を使ってください。

    とお願いしたんですが、それはやる気なしですか? 

    IIS が付属してないとか、社内の利用制限などで、できない事情が
    あればやむを得ませんが・・・

    でも、このフォーラムのほとんどの参加者は知らない Google のラ
    イブラリに関する問題は、ご自分の開発環境で問題を再現してデバ
    ッグできないと、これ以上話は進まないと思います。自分もこの先
    お役に立てることはなさそうです。

    2012年10月4日 12:41
  • 追加でのご助言、誠にありがとうございます。

    私の表現が悪かったのですが、ご指摘の内容は検証済みです。

    対象になっているDLLファイル全てを全てのユーザーをフルコントロールにしてみましたが、結果は変わりませんでした。

    しかし、今回、
    >読み書きにはストリームも含めて考える必要がある
    という点は、大変参考になりました。今まで、こういったことを意識することがありませんでしたので、今後、こういった点にも気をつけてみようと思います。


    ぷら

    2012年10月4日 18:34
  • こちら、表現が悪かったのですが、IISの検証はしてみたのですが、Win7HomePremiumのIISなので、これもテスト版みたいなものというおまけ付きで、参考になるかどうかは不明です。さらに、IISのバージョンも違ってしまい、本番環境に近いバージョンではチェックができておらず、というのが現状です。

    いちおう、ココに質問するからには、いただいた『可能性』は全て、できる範囲で検証するようにしています。


    ぷら

    2012年10月4日 18:49
  • 2つのレスにまとめて返信しますが。

    > 対象になっているDLLファイル全てを全てのユーザーをフルコントロールにしてみましたが、結果は変わりませんでした。

    IISの実行時ユーザーは特殊な権限を持っています。
    全てのユーザー、という範囲がなにを指しているのかわかりませんが、そういった点をきちんと認識したうえでの検証なのか
    この書き方だとわかりません。
    読んだ感じだと十分な検証はできてないようにも思えます。
    あと、これはないかもしれませんがDLLがレジストリ見てたり、ってことはないですか?
    その場合レジストリの読み込みや書き込みの権限が必要になることもあります。
    これらの点を含めてDLLに関するアクセス権関係はすべてクリアになっているのでしょうか?

    > さらに、IISのバージョンも違ってしまい、本番環境に近いバージョンではチェックができておらず、というのが現状です。

    VSからリモートのIISに接続してデバッグしながら動作させることが、、、ってそうか、VWDか。
    だとリモートでのデバッグはできないですね。

    テスト用に動かせるサーバーを仮想環境でもいいから用意できれば、そのうえにVWDのせてデバッグ実行してみて、とか
    できるかもしれませんが。


    あおい情報システム株式会社 小野修司(どっとねっとふぁん)

    2012年10月5日 1:22
  • いろいろと深いところまでアドバイスいただきまして、まことにありがとうございます。

    また、フルコントロールも抽象的な表現になってしまい、申し訳ありませんでした。

    まず、フルコントロールですが、今回の動作に絡んでいるすべてのフォルダ、ファイルに対して、
    サーバー上では
    ・アプリケーション プール アイデンティティ アカウント
    ・Anonymous Webユーザー
    ・認証されたFTPユーザー
    の、3つのユーザーから。ローカルでは
    ・System
    ・Administrator
    ・IIS_IUSRS
    ・自分
    からの、読み込み許可、書き込み許可、実行許可をすべて許可(True)にして動かしてみたということです。
    今までの理解では、サーバー上で動くプログラムは、『アプリケーション プール アイデンティティ アカウント』でログインしていると認識しています。
    なお、レンタルサーバーは専用サーバーではないのでおそらく資格に関して操作できないと思います。ので、もし、『アプリケーション プール アイデンティティ アカウント』の権限を越えた処理が必要になる場合は、今回考えている内容は実現不可ということになってしまいそうです。

    また、同様の理由で、レジストリを読みにいっていることがあれば、さすがにお手上げです。が、さすがにそこまで特殊な動きになるようであれば、そういった記載がどこかにありそうですが、探した限りでは見つかりませんでした。

    しかし、レジストリを読みに行くところも今まで意識したことがありませんでした。今回のこの問題で、かなり参考になることがありました。ありがとうございます。
    ちなみに、
    >IISの実行時ユーザーは特殊な権限を持っています。
    初めて知りました。ここはあまり理解できていないので、このあたりが理解できる資料などご存知でしたら教えていただけないでしょうか?

    デバッグについてですが、
    >VSからリモートのIISに接続してデバッグしながら動作させることが、、、ってそうか、VWDか。
    はい、VWDなのです(汗)。が、私の理解が間違えていなければ、ローカルIISのサイトを開くことが出来るので、IISのバージョンの違いはありますが、デバッグしながら動かせます。
    ところで、このデバッグではどのような点をチェックすればよろしいのでしょうか?すでに私では、権限関連で、デバッグで何をチェックしたらヒントが見えるのか?よくわからない、というか、私が理解できる範囲を超えてきている気がします。

    何卒よろしくお願いします。


    ぷら


    • 編集済み Pla 2012年10月5日 15:13 打ち消し線のカ所が間違えでしたので、訂正しました。以前使っていたサーバーがリモートリモートサイトで接続できたので、それと勘違いしていたようで、ローカルIISはVSのみのようです。
    2012年10月5日 7:40
  • > いちおう、ココに質問するからには、いただいた『可能性』は全て、
    > できる範囲で検証するようにしています。

    「検証」というのはどういう意味で使ってますか?

    何にせよ、自分が開発環境でも IIS を使うことをお勧めしている理由は
    運用環境と開発環境を同じにして、開発環境でも問題を再現し、原因を
    特定することなんですが。

    それをしない限り、今回のような問題をここで聞いても、解決策は得ら
    れないと思いますよ。

    2012年10月5日 13:27
  • >「検証」というのはどういう意味で使ってますか?

    表現がうまく伝わらず申し訳ありません。検証というのは、アドバイスに沿って実験してみた、試してみた、ということです。

    今回、テストサーバーは本番環境との違いから問題が起こる可能性があるということがわかりましたので、今後は開発環境でもIISを使っていこうと思いました。

    そして、Win7付属のIISで実行させると、期待通りの動作をします。

    前回も触れましたが、IISのバージョンの違いに起因する原因がない限り、ローカルでは動作に問題はなく、サーバー上で動作させると具合が良くないようです。


    ぷら

    2012年10月5日 15:17
  • > Win7付属のIISで実行させると、期待通りの動作をします。

    サーバーはレンタルだそうですから、開発環境で問題を再現できないと、
    解決するのは難しいですね。

    レンタルということで、一つだけ思い浮かぶのは、Trust Level の制限
    です。レンタルの共有サーバーの場合、Trust Level が Full でないこ
    とがあります。Full でない場合は、開発環境で trust 要素をレンタル
    サーバーと同レベルに設定して試してみてください。

    trust 要素 (ASP.NET 設定スキーマ)
    http://msdn.microsoft.com/ja-jp/library/tkscy493(v=vs.80).aspx


    これから先は、自助努力でお願いしますと言うしかないですが、その前に、
    以前のレスで気になった点をコメントしておきます。

    > まず、フルコントロールですが、今回の動作に絡んでいるすべての
    > フォルダ、ファイルに対して、

    Google のライブラリ (dll) がアクセスするリソースを含めて、ワーカー
    プロセスがアクセスするすべてのリソースを特定できているわけではない
    はずですので、

    > 読み込み許可、書き込み許可、実行許可をすべて許可(True)にして
    > 動かしてみたということです。

    としたのは、ご自分が思い当たる範囲だけであって、あまり意味がない
    (と言うより、逆に、余計なことをして混乱を招くだけ)と思います。

    それから、列挙されたアカウントが変です。問題はワーカープロセスの
    アカウントのみです(偽装してなければですが)。なので、Anonymous
    Webユーザー、認証されたFTPユーザー、System、Administrator、自分
    というのは関係ないはずです。手当たりしだい試したという感じですが、
    まずはワーカープロセスに限って試した方がいいと思います。

    それから、ワーカープロセスのアカウントも変です。Web サーバーは
    Windows 2003 R2 SP2 + IIS 6.0 とのことですが(一番最初の質問の情
    報)、「アプリケーション プール アイデンティティ アカウント」と
    いうのは正しいですか?

    IIS6 のデフォルトでのワーカープロセスのアカウントは NETWORKSERIVCE
    のはずです。ApplicationPoolIdentity が使えるのは Windows Server 2008
    SP2 以降です。

    Application Pool Identities
    http://www.iis.net/learn/manage/configuring-security/application-pool-identities

    Windows Server 2003 から、最新の 2008 R2 まで、IIS が使うアカウン
    トがどのように変わってきたかは、以下のページが参考になると思います。

    IIS 7 のアクセス許可
    http://awoni.net/tips/iis_acl/

    >>IISの実行時ユーザーは特殊な権限を持っています。
    > 初めて知りました。ここはあまり理解できていないので、このあたりが
    > 理解できる資料などご存知でしたら教えていただけないでしょうか?

    上に紹介したページに加えて、以下のページが参考になると思います。

    IIS 7.0 での組み込みユーザーとグループ アカウントとは
    http://technet.microsoft.com/ja-jp/library/dd939094.aspx

    2012年10月6日 4:54