C# 维护来自android的WCF webservice调用之间的状态

C# 维护来自android的WCF webservice调用之间的状态,c#,asp.net,wcf,wcf-data-services,C#,Asp.net,Wcf,Wcf Data Services,我在VB.NET中有一个项目,它使用asp.NET成员身份管理用户身份验证。现在我想为这个项目构建android应用程序,所以我决定学习WCF,并且我对WCF Web服务的掌握一般。现在我面临的问题是,当用户登录android应用程序时,会发生以下情况: 请求转到Web应用程序,用户凭据经过身份验证 之后,当用户尝试提交任何数据或尝试查看数据时,请求再次转到web应用程序,但现在web应用程序应该根据用户在第一次从成员身份验证登录请求中提供的凭据对用户进行身份验证 现在,我面临的问题是如何在ja

我在VB.NET中有一个项目,它使用asp.NET成员身份管理用户身份验证。现在我想为这个项目构建android应用程序,所以我决定学习WCF,并且我对WCF Web服务的掌握一般。现在我面临的问题是,当用户登录android应用程序时,会发生以下情况:

  • 请求转到Web应用程序,用户凭据经过身份验证
  • 之后,当用户尝试提交任何数据或尝试查看数据时,请求再次转到web应用程序,但现在web应用程序应该根据用户在第一次从成员身份验证登录请求中提供的凭据对用户进行身份验证

  • 现在,我面临的问题是如何在java(Android)的每会话服务调用模式下对asp.net成员身份中的每个WCF请求的用户进行身份验证。

    我认为有几种方法可以满足您的要求,但我已经想到(并编写了)几种不同的潜在解决方案,我在这里分享的是一些我认为将使用ASP.NET成员资格/角色提供程序“插入”到现有解决方案中的内容。希望我已经给了你足够的信息去做你需要做的事情,但是如果还有什么不清楚的地方,你可以随时发表评论并提出更多的问题

    在您的问题中,您描述了为现有客户端使用包含WCF服务的ASP.NET Web应用程序,但您希望扩展到使用Android(java)请求?鉴于ASP.NET成员资格提供程序使用了大量“幕后”SOAP交换(用于身份验证、授权和加密),这些交换似乎内置于服务参考框架中,因此编写java实现将是一项相当大的任务

    因此,我已经为您编写了一个示例,它将集成到同一个“后端”提供者,但也允许您从任何客户端发送SOAP请求,而不需要服务引用(例如,我使用它进行了测试)。。。我已经用C#编写了我的解决方案(正如WCF示例所用的),但是,您可以非常轻松地使用。我还没有为您提供加密和解密密码的方法,您必须自己研究这一点

    您需要在现有解决方案中实现一个新的.svc文件,并相应地创建新的web.config条目(我假设您已经知道如何创建basicHttpBinding和服务端点)

    您还需要复制方法调用(或者创建一个包含方法内容的新类,并从实现ServiceContract方法的任何位置引用它),删除“[PrincipalPermission(SecurityAction)”属性,并将下面的示例方法添加到新服务中。 e、 g.(使用微软的方法)-

    将成为:

        // Allows all Users to call the Add method        
        public double Add(double n1, double n2, string username, string token)
        {
            string isAuthorized = IsAuthorized(username, "Users", token)
            if (isAuthorized.Contains("Success")
                double result = n1 + n2;
                return result;
            else
               throw new Exception("Authorization Exception: " + isAuthorized);
        }
    
    以下是我的实现,集成到(下载自):

    IsolatedAuthService.svc

    <%@ServiceHost Language="C#" Debug="true" Service="Microsoft.ServiceModel.Samples.IsolatedAuthService" CodeBehind="IsolatedAuthService.cs" %>
    
    IsolatedAuthService.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace Microsoft.ServiceModel.Samples
    {
        // Define a service contract.
        [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
        public interface IIsolatedAuthService
        {
            [OperationContract]
            string IsAuthorized(string username, string roleName, string token);
            [OperationContract]
            string AuthenticateUser(string username, string encryptedPassword);
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using System.Web;
    using System.Web.Hosting;
    using System.Web.Security;
    using System.Web.Configuration;
    using System.Configuration;
    using System.IO;
    using System.Security.Permissions;
    using System.Security.Principal;
    using System.ServiceModel.Activation;
    using System.Threading;
    
    namespace Microsoft.ServiceModel.Samples
    {
        public class IsolatedAuthService : IIsolatedAuthService
        {
            public string IsAuthorized(string username, string roleName, string token)
            {
                MembershipUser user = Membership.GetAllUsers()[username];
    
                Configuration config = ConfigurationManager.OpenExeConfiguration(HostingEnvironment.MapPath("~") + "\\web.config");           
    
                SessionStateSection sessionStateConfig = (SessionStateSection)config.SectionGroups.Get("system.web").Sections.Get("sessionState");
    
                InMemoryInstances instance = InMemoryInstances.Instance;
    
                // Check for session state timeout (could use a constant here instead if you don't want to rely on the config).
                if (user.LastLoginDate.AddMinutes(sessionStateConfig.Timeout.TotalMinutes) < DateTime.Now)
                {
                    // Remove token from the singleton in this instance, effectively a logout.                
                    instance.removeTokenUserPair(username); 
                    return "User Unauthorized - login has expired!";
                }
    
                if (!instance.checkTokenUserPair(username, token))
                    return "User Unauthorized - not a valid token!";
    
                // Check for role membership.
                if (!Roles.GetUsersInRole(roleName).Contains(user.UserName))
                    return "User Unauthorized - Does not belong in that role!";
    
                return "Success - User is Authorized!";
            }
    
            public string AuthenticateUser(string username, string encryptedPassword)
            {
                if (Membership.ValidateUser(username, Decrypt(encryptedPassword)))
                {
                    // Not sure if this is actually needed, but reading some documentation I think it's a safe bet to do here anyway.
                    Membership.GetAllUsers()[username].LastLoginDate = DateTime.Now;
    
                    // Send back a token!
                    Guid token = Guid.NewGuid();
    
                    // Store a token for this username.
                    InMemoryInstances instance = InMemoryInstances.Instance;
                    instance.removeTokenUserPair(username); //Because we don't implement a "Logout" method.
                    instance.addTokenUserPair(username, token.ToString());
    
                    return token.ToString();
                }
    
                return "Error - User was not able to be validated!";
            }
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Microsoft.ServiceModel.Samples
    {
        public class InMemoryInstances
        {
            private static volatile InMemoryInstances instance;
            private static object syncRoot = new Object();
    
            private Dictionary<string, string> usersAndTokens = null;
    
            private InMemoryInstances() 
            {
                usersAndTokens = new Dictionary<string, string>();
            }
    
            public static InMemoryInstances Instance
            {
                get 
                {
                    if (instance == null) 
                    {
                        lock (syncRoot)                  
                        {
                            if (instance == null) 
                                instance = new InMemoryInstances();
                        }
                    }
    
                    return instance;
                }
            }
    
            public void addTokenUserPair(string username, string token)
            {
                usersAndTokens.Add(username, token);
            }
    
            public bool checkTokenUserPair(string username, string token)
            {
                if (usersAndTokens.ContainsKey(username)) {
                    string value = usersAndTokens[username];
                    if (value.Equals(token))
                        return true;
                }
    
                return false;
            }
    
            public void removeTokenUserPair(string username)
            {
                usersAndTokens.Remove(username);
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用System.Linq;
    使用System.Runtime.Serialization;
    使用System.ServiceModel;
    使用系统文本;
    使用System.Web;
    使用System.Web.Hosting;
    使用System.Web.Security;
    使用System.Web.Configuration;
    使用系统配置;
    使用System.IO;
    使用System.Security.Permissions;
    使用System.Security.Principal;
    使用System.ServiceModel.Activation;
    使用系统线程;
    命名空间Microsoft.ServiceModel.Samples
    {
    公共类IsolatedAuthService:IIsolatedAuthService
    {
    公共字符串已授权(字符串用户名、字符串角色名、字符串令牌)
    {
    MembershipUser=Membership.GetAllUsers()[username];
    配置配置=ConfigurationManager.OpenExeConfiguration(HostingEnvironment.MapPath(“~”+“\\web.config”);
    SessionStateSection sessionStateConfig=(SessionStateSection)config.SectionGroups.Get(“system.web”).Sections.Get(“sessionState”);
    InMemoryInstances实例=InMemoryInstances.instance;
    //检查会话状态超时(如果不想依赖配置,可以在此处使用常量)。
    if(user.lastloginandate.AddMinutes(sessionStateConfig.Timeout.TotalMinutes)
    InMemoryInstances.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace Microsoft.ServiceModel.Samples
    {
        // Define a service contract.
        [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
        public interface IIsolatedAuthService
        {
            [OperationContract]
            string IsAuthorized(string username, string roleName, string token);
            [OperationContract]
            string AuthenticateUser(string username, string encryptedPassword);
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using System.Web;
    using System.Web.Hosting;
    using System.Web.Security;
    using System.Web.Configuration;
    using System.Configuration;
    using System.IO;
    using System.Security.Permissions;
    using System.Security.Principal;
    using System.ServiceModel.Activation;
    using System.Threading;
    
    namespace Microsoft.ServiceModel.Samples
    {
        public class IsolatedAuthService : IIsolatedAuthService
        {
            public string IsAuthorized(string username, string roleName, string token)
            {
                MembershipUser user = Membership.GetAllUsers()[username];
    
                Configuration config = ConfigurationManager.OpenExeConfiguration(HostingEnvironment.MapPath("~") + "\\web.config");           
    
                SessionStateSection sessionStateConfig = (SessionStateSection)config.SectionGroups.Get("system.web").Sections.Get("sessionState");
    
                InMemoryInstances instance = InMemoryInstances.Instance;
    
                // Check for session state timeout (could use a constant here instead if you don't want to rely on the config).
                if (user.LastLoginDate.AddMinutes(sessionStateConfig.Timeout.TotalMinutes) < DateTime.Now)
                {
                    // Remove token from the singleton in this instance, effectively a logout.                
                    instance.removeTokenUserPair(username); 
                    return "User Unauthorized - login has expired!";
                }
    
                if (!instance.checkTokenUserPair(username, token))
                    return "User Unauthorized - not a valid token!";
    
                // Check for role membership.
                if (!Roles.GetUsersInRole(roleName).Contains(user.UserName))
                    return "User Unauthorized - Does not belong in that role!";
    
                return "Success - User is Authorized!";
            }
    
            public string AuthenticateUser(string username, string encryptedPassword)
            {
                if (Membership.ValidateUser(username, Decrypt(encryptedPassword)))
                {
                    // Not sure if this is actually needed, but reading some documentation I think it's a safe bet to do here anyway.
                    Membership.GetAllUsers()[username].LastLoginDate = DateTime.Now;
    
                    // Send back a token!
                    Guid token = Guid.NewGuid();
    
                    // Store a token for this username.
                    InMemoryInstances instance = InMemoryInstances.Instance;
                    instance.removeTokenUserPair(username); //Because we don't implement a "Logout" method.
                    instance.addTokenUserPair(username, token.ToString());
    
                    return token.ToString();
                }
    
                return "Error - User was not able to be validated!";
            }
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Microsoft.ServiceModel.Samples
    {
        public class InMemoryInstances
        {
            private static volatile InMemoryInstances instance;
            private static object syncRoot = new Object();
    
            private Dictionary<string, string> usersAndTokens = null;
    
            private InMemoryInstances() 
            {
                usersAndTokens = new Dictionary<string, string>();
            }
    
            public static InMemoryInstances Instance
            {
                get 
                {
                    if (instance == null) 
                    {
                        lock (syncRoot)                  
                        {
                            if (instance == null) 
                                instance = new InMemoryInstances();
                        }
                    }
    
                    return instance;
                }
            }
    
            public void addTokenUserPair(string username, string token)
            {
                usersAndTokens.Add(username, token);
            }
    
            public bool checkTokenUserPair(string username, string token)
            {
                if (usersAndTokens.ContainsKey(username)) {
                    string value = usersAndTokens[username];
                    if (value.Equals(token))
                        return true;
                }
    
                return false;
            }
    
            public void removeTokenUserPair(string username)
            {
                usersAndTokens.Remove(username);
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用System.Linq;
    使用系统文本;
    名称空间微软