我的Membership ValidateUser请求有什么问题? (使用ClientFormsAuthenticationMembershipProvider)

时间:2009-08-28 19:19:09

标签: asp.net vb.net authentication asp.net-membership membership

我是否可以运行任何简单的诊断来确定身份验证不适用于ClientFormsAuthenticationMembershipProvider提供程序的原因?我的问题:

我有一个托管在服务器A上的网站(我们将其称为“身份验证者”网站),该网站配置为使用AspNetSqlMembershipProvider提供程序进行成员资格和角色管理。我认为该网站的相关web.config密钥是:

    <membership>
        <providers>
            <clear />
            <add name="AspNetSqlMembershipProvider"
                 type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                 connectionStringName="MMMS35.API"
                 enablePasswordRetrieval="false"
                 enablePasswordReset="true"
                 requiresQuestionAndAnswer="false"
                 applicationName="Moose"
                 requiresUniqueEmail="false"
                 passwordFormat="Hashed"
                 maxInvalidPasswordAttempts="5"
                 minRequiredPasswordLength="7"
                 minRequiredNonalphanumericCharacters="0"
                 passwordAttemptWindow="1"
                 passwordStrengthRegularExpression="" />
        </providers>
    </membership>
    <profile>
        <providers>
            <clear />
            <add name="AspNetSqlProfileProvider"
                 connectionStringName="MMMS35.API"
                 applicationName="Moose"
                 type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
        </providers>
    </profile>
    <roleManager enabled="true">
        <providers>
            <clear />
            <add name="AspNetSqlRoleProvider"
                 connectionStringName="MMMS35.API"
                 applicationName="Moose"
                 type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
        </providers>
    </roleManager>

我在与服务器A相同的网络上托管在服务器B上的另一个网站(称为“测试客户端”网站),但我确实知道服务器A之间的网络路径,路由器配置等&安培; B. Test Client有一个模拟登录设置,它使用ClientFormsAuthenticationMembershipProvider提供程序要求“Authenticator”网站验证Test Client上提供的凭据。测试客户端的相关web.config部分是:

    <membership defaultProvider="ClientAuthenticationMembershipProvider">
        <providers>
            <clear/>
            <add name="ClientAuthenticationMembershipProvider"
                 type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                 serviceUri="http://slmooseapp1/mia/Authentication_JSON_AppService.axd"
                 credentialsProvider=""
                 savePasswordHashLocally="False"/>
        </providers>
    </membership>
    <roleManager defaultProvider="ClientRoleProvider" enabled="true">
        <providers>
            <clear/>
            <add name="ClientRoleProvider"
                 type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                 serviceUri="http://slmooseapp1/mia/Role_JSON_AppService.axd"
                 cacheTimeout="1"/>
        </providers>
    </roleManager>

当测试客户端执行此行时:

DirectCast(Membership.Provider, ClientServices.Providers.ClientFormsAuthenticationMembershipProvider).ValidateUser(UserName.Text, Password.Text)

我得到一个例外:

System.UnauthorizedAccessException: Access to the path 'C:\Documents and Settings\Default User\Application Data\Microsoft Corporation\Internet Information Services\6.0.3790.3959' is denied.

但是,当我在我的开发箱(而不是服务器B)上使用完全相同的web.config serviceUri路径运行测试客户端时(即,我的客户端成员资格提供程序指向服务器A上的同一个身份验证网站),验证用户并获得该用户的角色非常有效。

如果我在服务器B上打开浏览器并从身份验证网站请求页面,则身份验证Web应用程序运行正常,因此我知道我可以成功地从服务器B向服务器A发出http请求。 ClientFormsAuthenticationMembershipProvider在尝试从服务器B向服务器A发出JSON请求(我认为是)时失败了什么?

编辑(9/21/2009):

我现在已经尝试了这种情况,身份验证网站和测试客户端在同一个盒子上(这不是我的开发机器)。它仍然失败。我以编程方式编写了一个原始的Http请求,并且DID获得了成功的响应......

请求:

Content-Type: application/json
Host: slappdev
Content-Length: 70
Expect: 100-continue
Connection: Keep-Alive

{"userName":"mdh","password":"test123","createPersistentCookie":false}

响应:

MicrosoftOfficeWebServer: 5.0_Pub
Content-Length: 10
Cache-Control: private, max-age=0
Content-Type: application/json; charset=utf-8
Date: Mon, 21 Sep 2009 20:10:13 GMT
Set-Cookie: AppName=1756811D52C4619AC78...; path=/; HttpOnly
Server: Microsoft-IIS/6.0
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET

{"d":true}

所以,我的猜测是,在通过.Net框架调用从ValidateUser获取实际的HTTP请求时出现问题。有什么想法吗?

编辑(9/22/2009)

抛出的异常与我的测试客户端网页尝试访问System.Windows.Forms.Application.UserAppDataPath时引发的完全相同的异常。将connectionStringName属性添加到客户端Web应用程序的web.config文件中指向有效连接字符串名称的membership / providers / add键会更改异常!

System.Data.SqlClient.SqlException: Invalid object name 'ApplicationProperties'. at System.Data.SqlClient.SqlConnection.OnError

因此,如果所有成员函数都使用serviceUri,为什么在客户端本地尝试任何事情?并且,我需要运行哪些实用程序来将这些新表/对象添加到我的数据库中以支持客户端成员资格提供程序?

2 个答案:

答案 0 :(得分:2)

ClientAuthenticationMembershipProvider具有脱机缓存功能。如果无法访问实际的成员资格提供程序,则客户端成员资格提供程序可以在客户端计算机上缓存凭据并使用这些脱机凭据。此脱机缓存由自动生成并存储在System.Windows.Forms.Application.UserAppDataPath位置的SQL Server Compact Edition数据库文件表示。

根据this MSDN article,您可以配置本地脱机缓存以使用数据库。您必须手动创建文章中指定的数据库表(在我的9/22编辑中,我还没有创建这些表,并且没有实用程序可以这样做)。我这样做了,但客户端仍然想在本地机器上为本地SQL CE文件创建文件夹结构,即使它永远不会创建这样的文件。对于我测试中的每台计算机,除了本地工作站之外,IIS用户无权为本地缓存数据库构建该文件夹结构,这会生成UnauthorizedAccessException。

我很不高兴A)没有配置密钥来关闭成员资格的离线缓存,B)即使将离线缓存指向数据库,客户端成员资格提供者仍然必须建立一个文件夹路径到它永远不会创建的本地缓存文件。

答案 1 :(得分:0)

如果在web.config文件中添加system.diagnostic标记,则可以正常工作。 (我这里只是一个空文件,但也没有错误信息。)

 <system.diagnostics>
        <sources>
            <!-- This section defines the logging configuration for My.Application.Log -->
            <source name="DefaultSource" switchName="DefaultSwitch">
                <listeners>
                    <add name="myListener"/>
                    <!-- Uncomment the below section to write to the Application Event Log -->
                    <!--<add name="EventLog"/>-->
                </listeners>
            </source>
        </sources>
        <switches>
            <add name="DefaultSwitch" value="Information" />
        </switches>
        <sharedListeners>
          <add    name="myListener"
                       type="System.Diagnostics.TextWriterTraceListener"
                       initializeData="c:\temp\MyFile.log" />
            <!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
            <!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
        </sharedListeners>
    </system.diagnostics>