メンバーシップ プロバイダーとロール プロバイダーを使用する既存の C# ASP.NET Web アプリケーションがあります。これらのテーブルは、すべてのアプリケーション テーブルを保持する同じ DB でホストされます (運用環境では Azure、開発環境ではローカル SQLExpress でホストされます)。
同じユーザーとロール情報を使用するコンソール アプリケーションを作成したいと考えています。この目的のために、(コンソール アプリで) クライアント アプリケーション サービスを有効にし、これらをコンソール アプリに公開する新しい Web サービスを追加しました。
これをテスト セットアップ (コンソールと winforms の両方) で動作させることができます。つまり、Web サービスがユーザー/ロールの独自の空のセットを作成し、これを読み取ってローカル ファイルに SQL CE データベースとして保存します。
Web サービスがアプリケーションの DB から読み取れるようにするにはどうすればよいですか?
元の Web アプリケーションに関連する web.config:
<profile defaultProvider="DefaultProfileProvider">
<providers>
<add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="SecondBiteDBContext" applicationName="/" />
</providers>
</profile>
<membership defaultProvider="DefaultMembershipProvider">
<providers>
<add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="SecondBiteDBContext" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="10" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<roleManager defaultProvider="DefaultRoleProvider" enabled="true">
<providers>
<add name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="SecondBiteDBContext" applicationName="/" />
</providers>
</roleManager>
Web サービスの Web.config:
<system.web.extensions>
<scripting>
<webServices>
<authenticationService enabled="true" requireSSL="false" />
<profileService enabled="true" readAccessProperties="WebSettingsTestText" writeAccessProperties="WebSettingsTestText" />
<roleService enabled="true"/>
</webServices>
</scripting>
</system.web.extensions>
....
<system.web>
<profile enabled="true" >
<properties>
<add name="WebSettingsTestText" type="string"
readOnly="false" defaultValue="DefaultText"
serializeAs="String" allowAnonymous="false" />
</properties>
</profile>
</system.web>
コンソール アプリの App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="ClientSettingsProvider.ServiceUri" value="http://localhost:31337/SecondBiteAppServices/Profile_JSON_AppService.axd" />
<add key="ClientSettingsProvider.ConnectionStringName" value="DefaultConnection" />
</appSettings>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;Initial Catalog=SBAuto;MultipleActiveResultSets=True;Integrated Security=SSPI" />
</connectionStrings>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="http://localhost:31337/SecondBiteAppServices/Authentication_JSON_AppService.axd" connectionStringName="DefaultConnection" savePasswordHashLocally="False" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="http://localhost:31337/SecondBiteAppServices/Role_JSON_AppService.axd" cacheTimeout="86400" connectionStringName="DefaultConnection" />
</providers>
</roleManager>
</system.web>
</configuration>
フォームを使用していないため、オプションの資格情報プロバイダーを指定していません。現在、validateuser() へのハードコードされた呼び出しを成功させることはできません。
プロジェクト プロパティ -> [サービス] タブ -> [詳細] ボタンを使用して、必要な DB を指すカスタム接続文字列を指定しました。しばらくの間、「無効なオブジェクト ApplicationProperties」に関する例外が発生していたため、DB に接続していることはわかっています。DB に列 PropertyName と PropertyValue を持つテーブルを作成すると、これが修正されました。DB で既に aspnet_regsql を実行していたことに注意してください。これにより、必要なテーブルが作成されているはずです。
ただし、そのDBに存在するユーザーの検証チェックに合格していません-正常に実行されますが(例外はありません)、ログインに失敗します。上記の app.config の構造に基づいて、カスタム接続文字列はプロファイル サービスにのみ適用され、メンバーシップまたは役割サービスには適用されないのではないでしょうか? (プロファイル サービス [クライアント設定プロバイダー] のみが接続文字列をパラメーターとして取っています。)接続文字列は、オフラインのローカル キャッシュのものを格納するためだけのものです。
プロジェクト -> asp.net 構成 (Web サービス プロジェクトを選択) を使用すると、Web サイト管理ツールでは、プロバイダーを構成したり、新しいプロバイダーを追加したりする意味のあることは何もできません。
そのDBで実際にユーザーとロールを使用できるようにするものを追跡することはできませんでした. 何か案は?(私は .net にかなり慣れていないので、何かが欠けている可能性は十分にありますが、ドキュメンテーションで多くの問題を抱えており、Google から適切な結果を得ています。)
これが機能したら、さまざまなプロジェクト間でビジネス ロジックを共有したいと考えています。現在、ロジックはメインの Web アプリ コントローラー メソッドにあります。明らかに、それを共有レイヤーにリファクタリングする必要があります。関連するオブジェクトがエンティティ フレームワークに基づいている場合、それは可能でしょうか?
このすべてのクライアント サービスの作業を開始する前に、試用版のリファクタリングを行いました。私はすべてを参照してコンパイルすることができましたが、コードは実行の非常に早い段階で静かに失敗していました。私の最善の推測は、さまざまなフレームワーク関連のものすべてが適切に初期化されていなかったため、クライアントアプリサービスに入ったということでした。ただし、CAS を実行しても、エンティティ フレームワークが引き続き問題を引き起こすのではないかと心配しています。
最後の 1 つ: 異なるプロジェクトの構成ファイル間で構成要素 (主に接続文字列) を共有するにはどうすればよいですか? 複数のファイルを編集することなく、開発と本番の間でスワップできるようにしたいと考えています。
編集:このようなことをしているハックの量はどれくらいですか? http://devpinoy.org/blogs/comgen/archive/2007/08/15/use-membership-api-in-winforms.aspx 直接関連していなくても、これが私が見つけた唯一の実際に役立つものですCASへ。メインの Web アプリ web.config から適切な行をコピーするだけでよいようです (これには、DB の接続文字列へのリンクが含まれています)。
ありがとう!
25/1/13 更新:上記の web.config 要素を置き換えて、上記の編集済みリンクで提案されている代替案を試しました (ただし、system.web.providers.dll を bin/debug ディレクトリに手動でコピーする必要もありました) )。validateuser() をきれいに呼び出すことはできますが、それでもログインは許可されません。SQL プロファイラーでアクティビティが発生しており、ユーザー テーブルの最後のアクティビティ タイムスタンプが更新されているため、DB にアクセスしていることはわかっています。これは、CAS の方法では発生しません。
更新 25/1/13 #2 - 過去 4 時間を費やして、なぜ失敗したのかをデバッグしようとしました。(デバッグではなく) コードを読むと、提供されたパスワード ハッシュと保存されているパスワード ハッシュの比較に失敗していることがわかります。正しいユーザーとパスワードを提供していると 100% 確信しています。Microsoft は system.web.providers.dll のコードを公開していないため、デバッグに関しては、DefaultMembershipProvider.ValidateUser が呼び出されるため、membership.validateuser 呼び出し以外に踏み込むことはできません。
Resharper は DefaultMembershipProvider のソース コードを (逆コンパイルして) 表示しますが、デバッグすることはできません。dll全体をプロジェクトに逆コンパイルし、dllへの参照を削除してからプロジェクトを追加できることを他の場所で読みました。
そうしようとして、私は次の問題を抱えていました:
Dis# を使用すると、ロットをプロジェクトとして保存できますが、多くのエラーでいっぱいの一見管理されたソースが生成されます。ほとんどの場合、変数名が正しくない場所での構文エラーのようです。プロジェクトをインポートすると、VS はターゲットの .net バージョンの変更について警告しますが、これは何もしていないようです
Telerik JustDecompile を使用してプロジェクトを保存できますが、system.web.providers.resources.providerresources.resx を補完する .cs ファイルが含まれていませんでした。動作する Dis# から .cs をインポートしました。ただし、エラーはまだいっぱいありますが、さまざまなエラー (ただし、いくつかの構文に関連しています) があり、それほど多くはありません。それらのかなりの数は、他の system.x 名前空間のクラスと関係があります。参照としてロットを追加するブランケットは、何の役にも立ちませんでした。
ILSpy - dll を開くと、JustDecompile プロジェクトが参照していると思われる他の名前空間の部分が一覧表示されます。しかし、ファイルを1つずつ保存することしかできず、数十のdllファイルの構造を手作業で再構築しようとすることにあまり興味がありません...
これは何かを逆コンパイルする私の最初の試みですが、私が見つけたものはすべて、私がやっていることはうまくいくはずであることを示しているようです (しかし、彼らは確かに私が抱えていた問題について言及していませんでした)。次に何をすべきかについてのアイデアはありますか?
OP で試行した Web サービスに関する補足: aspnet_regsql.exe によって、"aspnet_" というプレフィックスが付いたメンバーシップ テーブルとロール テーブルの重複セットが作成されていることに気付きました。たとえば、私の既存のアプリ/コードは単純なメンバーシップのみを使用していますが、aspnet_membership です。これにより、Web サービスが別のテーブルをチェックしていたため、データが読み取られなかった理由が明らかになりました。
2 つのスキーマ間でデータを移行するためのコードを書いた人に関するブログを見つけました (現在はリンクが見つかりません)。これは、テーブルの異なるセットがメンバーシップ (など) プロバイダーの異なるバージョンに関連していることを示しています。したがって、「ユニバーサル プロバイダー (system.web.providers) に表示されるプロバイダーは、クライアント アプリケーション サービスで使用され、作成した Web サービスによって公開されるプロバイダーとは異なる (そして互換性がない) と想定しています。