使用WCF服务验证ASP.NET Web应用程序

时间:2009-07-05 21:59:33

标签: asp.net wcf web-services

背景

我有一个与WCF服务交互的ASP.NET Web应用程序。 Web应用程序和WCF服务由我控制。 ASP.NET Web应用程序使用ASP.NET成员资格提供程序模型的自定义实现(密码以散列形式存储)来验证登录Web应用程序的用户。 ASP.NET Web应用程序和WCF服务都可以访问相同的成员资格数据库。

由于用户只提供一次密码,我不想将密码存储在任何地方或者通过反复要求他们重新提供密码来惹恼他们,我需要一个适当的机制来通过WCF对用户进行身份验证服务。

基于我看到的其他问题和答案,我正在考虑一种“登录会话”方法,当用户最初登录到Web应用程序时,将在自定义成员资格数据库中创建登录会话,由GUID标识的登录会话,并在一段时间不活动后自动过期。 Web应用程序将为每个登录用户“记住”登录会话GUID(存储在表单身份验证故障单或会话中)。

WCF服务还将提供自己的登录操作,接受用户名和密码,并返回登录会话GUID,如上所述。

然后,WCF服务将接受所有其他操作的登录会话GUID,并在允许操作继续之前验证GUID是否表示尚未过期的有效登录会话。

我已经做了相当多的背景阅读,并且有很多关于直接使用UserName客户端凭证类型的材料,但这需要Web应用程序记住用户的密码,这似乎不是对我来说是一个好主意。

我已经完成了一些研究,并在MSDN上找到了材料,但这似乎是很多努力来实现(至少对我来说)似乎是一种非常常见的使用场景。

How to: Create a Custom Token

问题

上述“登录会话”的一般方法是否合理?
如果是这样,实现它的最佳方法是什么? 如果没有,你能建议一个替代方案吗?

6 个答案:

答案 0 :(得分:2)

这是一种非常合理的方法。

要执行此操作,请设置服务端点并使用自定义成员资格提供程序对其进行配置(您可以对SQL成员资格提供程序执行相同操作,但不需要自定义成员资格提供程序。)

在Web应用程序上,您设置Login控件的Authenticate事件以实例化新服务代理,并在代理中的ClientCredentials中设置用户名/密码。

现在,当您通过代理调用服务时,WCF会将这些凭据通过安全通道传递给服务并使用它们进行身份验证。

现在,您只需将代理存储在会话中,并将其用于将来访问服务,因为它具有通道状态和私钥。

protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e)
{
    bool Authenticated = false;
    try
    {
        MyServiceClient proxy = new MyServiceClient("MyServiceEndpoint");
        proxy.ClientCredentials.UserName.UserName = LoginControl.UserName;
        proxy.ClientCredentials.UserName.Password = LoginControl.Password;

        //It doesn't really matter what is called or what it does because 
        //Membership Provider for the Service does the authentication.
        string retval = proxy.login("Logging in"); 

        //Now that channel is established the proxy needs to be kept
        //since it contains the channel state which includes a private key
        Session["MyServiceProxy"] = proxy;  
        Authenticated = true;
    }
    catch (Exception ex)
    {
        //Login Error...
    }
    e.Authenticated = Authenticated;
}

答案 1 :(得分:1)

我能想到两种可能的解决方案:

首先,如果WCF服务是内部服务,则Web应用程序可以发送每个请求请求数据的用户的名称。

第二个是你在某处存储用户名和密码(或实际密码)的哈希值。在会话状态或用户cookie中(存储在内存中的会话cookie通过https传递给用户)。然后在每次请求时将用户名和密码传递给WCF服务。

答案 2 :(得分:1)

请参阅Storing password in forms authentication cookie - ASP.NET and WCF calls上的答案,了解不需要存储密码的解决方案。

答案 3 :(得分:1)

感谢大家的投入。我已经确定了一种方法(至少目前为止)。它非常简单,适用于我的目的。

使用“UserName”clientCredentialType和返回安全令牌的显式服务登录方法(为简洁起见省略了令牌生成详细信息),服务客户端可以决定是否将真正的密码作为客户端凭据上的密码属性或而是安全令牌(从登录方法获得)。如果客户端是Web应用程序,则安全令牌可以存储在表单身份验证票证,会话或任何位置。

使用“Custom”userNamePasswordValidationMode和UserNamePasswordValidator的自定义实现,验证程序检查密码以确定它是有效的安全令牌还是密码 - 如果是密码,则客户端凭据将针对用户存储进行身份验证(SQL Server数据库),如果它是安全令牌,则检查它是否有效,未过期,并且属于用户名。

答案 4 :(得分:0)

我建议您查看Geneva,其目的在于解决您的情景。基本思想是通过HttpModule为WCF服务和ASP站点要求相同的安全令牌。该令牌将在针对您的会员数据库进行身份验证后发布,并且可能包含有关用户的有用信息(声明)。

对于介绍,您可以阅读Bustamante's article

答案 5 :(得分:0)

Microsoft提供了一个WCF服务,您可以使用该服务对使用ASP.NET成员身份的用户进行身份验证。

代码实际上构建在框架中 - 您只需要创建一个.svc文件来使用它。

http://msdn.microsoft.com/en-us/library/bb398990.aspx

相关问题