查找通过WCF登录网站的人的身份

本文关键字:身份 网站 登录 WCF 查找 | 更新日期: 2023-09-27 18:15:20

我有一个网站与ASP运行。会员数据库,它工作得很好。我也有一个WCF服务运行,它应该作为应用程序的API实现到网站(在我的情况下游戏)。现在我的问题是,我希望我的应用程序能够调用WCF,并通过我的数据库解决方案返回当前登录到网站的用户,我找不到一种方法来做到这一点。我试过使用:

OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name;

但这似乎没有一个值(null),当它是由登录在网站上的会话调用。我希望我的WCF能够根据谁在运行应用程序时登录来更新高分等东西,这是不可能的,据我所知,如果我不能抓住登录的人的身份。下面是我的测试方法:

protected void Page_Load(object sender, EventArgs e)
{
    APIHostClient client = new APIHostClient();
    client.Open();
    String name = client.GetUserName();
    Label.Text = name;
    client.Close();
}
// on the wcf side 
public String GetUserName()
    {
        String userName = OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name;
        return userName;
    }

web . config:

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IAPIHost" >
          <security mode ="TransportWithMessageCredential">
            <transport clientCredentialType="None"/>
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="https://localhost:2105/APIHost.svc" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IAPIHost" contract="ServiceReference1.IAPIHost"
        name="BasicHttpBinding_IAPIHost" />
    </client>
    <services>
      <service behaviorConfiguration="behavior" name="ICanHasGamez.APIHost">
        <endpoint address="" binding="basicHttpBinding" contract="ICanHasGamez.IAPIHost">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="behavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceCredentials>
            <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfService.SecurityValidator, WcfService"/>
          </serviceCredentials>
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
      multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

我似乎在这个主题上找到的所有信息都与您提供凭据的用户的标准身份验证有关,而我的问题是找到登录到我网站的人的凭据。

编辑:

我从错误的角度看待这个问题。这就是我目前试图修复它的方式:当用户访问包含应用程序的页面时,我生成一个SessionId,该页面包含有关应用程序ID、访问该页的用户ID和会话过期日期(当前日期+时间)的信息。显然你可以直接转发信息. swf文件主机(例如:http://helpx.adobe.com/flash/kb/pass-variables-swfs-flashvars.html),所以我将用户的sessionId传递给应用程序,应用程序开发人员可以使用访问用户的名称在数据库中通过一个SQL查询返回的sessionId认识用户ID(可以让它返回这个名字,但是ID对于我来说更有用)。如果我使这个解决方案工作,我会更新答案。

查找通过WCF登录网站的人的身份

如果您的web服务将从浏览器调用(如jQuery AJAX调用),那么您只需要与ASP. js并行托管WCF服务。Net应用程序,并启用ASP。Net兼容模式下的WCF服务。本文在msdn

中对此进行了描述。

我可以看到你已经在web中启用了asp.net兼容模式。通过添加

来配置
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" 
     multipleSiteBindingsEnabled="true" />

到web.config的<service.serviceModel>元素。

您还应该将[AspNetCompatibilityRequirements]属性设置为您的服务实现,如:

namespace ICanHasGamez
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class APIHost: IAPIHost
    {
        ...

允许访问HttpContext.Current,所以你现在可以得到用户名,如:

public String GetUserName()
{
    return HttpContext.Current.User.Identity.Name;
}

然而,如果你想从。net web应用程序的服务器端代码调用WCF服务,那么你还需要一种方法来模拟在客户端浏览器中调用该服务时登录的用户。Wiktor的答案提供了一种方法,通过发送ASP中接收到的身份验证cookie。. Net web应用程序到WCF服务

这样做可不容易。

您尝试做的是尝试从服务器调用您的WCF。这意味着服务器必须以某种方式模拟请求,将调用者的身份传递给被调用的WCF请求。

至少有几种方法可以做到。

最简单的方法是将身份验证cookie从请求(可通过request . cookies访问)复制到wcf客户端。我已经写了一篇关于如何做到这一点的博文

http://netpl.blogspot.com/2011/11/managing-cookies-in-wcf-client.html

这样做的好处是在网站和wcf中重用相同的身份验证方案(即表单身份验证),因此您的wcf对于内部和外部请求都是安全的。

编辑:既然你有问题,这是怎么做的:

APIHostClient client = new APIHostClient();
client.SetCookie( FormsAuthentication.FormsCookieName, this.Reuqest.Cookies[FormsAuthentication.FormsCookieName].Value );
client.Open();

(假设SetCokie在WCF端实现,如博客条目中所述)

我的编辑方案成功了。将sessionId作为FlashVars传递给flash文件,flash程序将有权访问唯一的sessionId字符串。这样就可以很容易地通过SQL查询访问各种信息。我必须在脚本中编写保存flash对象的asp.net代码,以便能够操作参数,因为相同的.aspx页面将用于保存不同用户连接的不同应用程序(querystring)。

hfSessionId =隐藏字段,该字段已设置为后面代码中的SessionId值。

      <script lang="javascript">
            function writeObjectTag() {
                var sessionId = document.getElementById('<%=hfSessionId.ClientID%>').value;
                document.writeln('<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="550" height="400" id="myFlashGame" align="middle">');
                document.writeln('<param name="movie" value="sessionIdDisplayer.swf" />');
                document.writeln(buildParamTag(sessionId));
                document.writeln('<object type="application/x-shockwave-flash" data="sessionIdDisplayer.swf" width="550" height="400">');
                document.writeln('<param name="movie" value="sessionIdDisplayer.swf" />');
                document.writeln(buildParamTag(sessionId));
                document.writeln('<a href="http://www.adobe.com/go/getflash">');
                document.writeln('<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />');
                document.writeln('</a>');
                document.writeln('</object>');
                document.writeln('</object>');
            }
            function buildParamTag(value) {
                return '<param name="FlashVars" value="' + value + '" />';
            }
      </script>