【问题标题】:ASP.NET Membership Authentication in WCF serviceWCF 服务中的 ASP.NET 成员身份验证
【发布时间】:2016-02-11 09:06:09
【问题描述】:

我正在尝试使用 WCF 服务扩展现有的 ASP.NET 应用程序。该服务必须要求通过站点其余部分使用的相同成员资格提供程序进行身份验证。

这是 web.config 文件:

<configuration>
<system.web>
  <compilation debug="true" targetFramework="4.5.2" />
  <httpRuntime targetFramework="4.5.2" />
  <authentication mode="Forms">
    <forms name=".MyAppAuthentication" timeout="5760" slidingExpiration="true" />
  </authentication>
  <roleManager enabled="true" defaultProvider="AspNetSqlRoleProvider">
    <providers>
      <clear />
      <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="UsersContext" applicationName="MyApp" />
    </providers>
  </roleManager>
  <membership defaultProvider="AspNetSqlMembershipProvider">
    <providers>
      <clear/>
      <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="UsersContext" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="10" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="MyApp"/>
    </providers>
  </membership>
</system.web>
<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  <bindings>
    <wsHttpBinding>
      <binding name="MembershipBinding">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="UserName"/>
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <behaviors>
    <serviceBehaviors>
      <behavior name="MembershipBehaviour">
        <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false"/>
        <serviceAuthorization roleProviderName="AspNetSqlRoleProvider" principalPermissionMode="UseAspNetRoles" />
        <serviceCredentials>
          <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="AspNetSqlMembershipProvider" />
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <services>
    <service name="ServiceTestBackend.Services.TestService" behaviorConfiguration="MembershipBehaviour">
      <endpoint address="" binding="wsHttpBinding" bindingConfiguration="MembershipBinding" contract="ServiceTestBackend.Services.ITestService" />
    </service>
  </services>
</system.serviceModel>
<connectionStrings>
  <add name="UsersContext" connectionString="data source=.;initial catalog=MyApp.Accounts;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>

服务的代码很简单:

public class TestService : ITestService
{
    public string FindUser()
    {
        var user = Membership.GetUser();
        return user.UserName;
    }
}

客户端就这么简单

var client = new TestService.TestServiceClient();
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
var acc = client.FindUser();

服务器被调用,但方法失败,因为Membership.GetUser()返回null

我是否遗漏了配置中的任何内容?

【问题讨论】:

  • 你想在服务器端获取客户端身份,对吧?
  • @EmmanuelDURIN,是的,我希望使用客户端指定的凭据执行服务器端的代码。
  • 我只是更仔细地阅读您的配置,我认为我的回答很糟糕。我刚刚删除了我的帖子。您的代码应该可以工作...但是在配置中为什么要创建自定义绑定?
  • 出于测试目的,避免使用 SSL。无论如何,启用 SSL 不会影响这种情况。
  • 愚蠢的问题:{username/password} 用户是否存在于您的数据库中?如果不是,则无法将身份添加到当前用户。

标签: c# asp.net wcf asp.net-membership


【解决方案1】:
  • 试试这样的代码:
public string FindUser()
{
   if (ServiceSecurityContext.Current != null)
       return ServiceSecurityContext.Current.PrimaryIdentity.Name;
   return null;
}
  • 您也可以从以下位置获取用户名:
IPrincipal principal = Thread.CurrentPrincipal;
String user = principal.Identity.Name
  • 最后,如果您真的想从 HttContext.Current.UserMembership.GetUser() 获取名称 - 因为您有很多现有代码 - 您可以编写用于身份验证的自定义模块:

看我的帖子:https://stackoverflow.com/a/33523683/5295797
并仔细阅读模块的实现部分。
还可以从该帖子中的链接下载完整的项目。

问候

【讨论】:

    【解决方案2】:

    我认为这里有些混乱。我不确定你到底想做什么。这样做可以让这一切变得非常简单。

      public class TestService : ITestService
      {
         public string FindUser(string userName, string password)
         {
            var user = Membership.GetUser(username, password);
            return (user!=null?user.userName: string.Empty);
         }
     }
    

    你的客户应该是这样的;

     using(var client = new TestService.TestServiceClient())
     {
         var response = client.FindUser(username, password);
         //validate the response
     }
    

    【讨论】:

    • 我正在尝试配置服务,以便它在经过身份验证的环境中执行。例如,必须设置HttpContext.Current.User 才能使代码的某些部分正常工作。显式传递凭据似乎是个坏主意,因为它破坏了兼容性并重新发明了轮子。
    • 所以客户端不是一个单独的应用程序,而是你的主应用程序的一部分?这意味着客户端和服务器共享相同的 HttpContext?
    • 没有。有两个独立的部分:IIS 托管的后端和控制台前端。我从前端发送请求并指定登录名和密码,这里一切正常。但随后后端开始执行代码,HttpContext.Current.User 为空,就好像我没有指定任何凭据一样。这是我正在尝试解决的不良行为。
    • 当您说“从前端发送请求并指定登录名和密码”并且一切正常时,您的意思是什么?您能否在服务器端身份验证方法处设置断点,并查看您是否在服务器上接收到用户名/密码,并且用户是否已正确通过身份验证?可能已经知道,如果 Current.User 为 null,则用户尚未通过身份验证。
    • 我没有明确实现的身份验证方法。如果我正确指定绑定安全性,它是否应该由会员资格提供者自动执行,还是我错了?我已经稍微更新了配置文件以使其更加明确。
    猜你喜欢
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-04
    • 1970-01-01
    • 2011-02-06
    • 2010-11-24
    • 2013-02-22
    相关资源
    最近更新 更多