您的位置:首页 > 编程语言 > ASP

利用WCF共享ASP.NET session实现WCF服务端验证

2011-10-31 15:54 555 查看
WCF能够共享ASP.NET的session,不同的WCF客户端代理类在采用Per Call模式下访问WCF能够访问同一个ASP.NET Session.但是WCF的Session和ASP.NET的Session是不同的。

WCF的Session代表着服务实例,它是被客户端代理类访问时初始化的。WCF依靠消息通道,安全回话和消息模式等来联系session的。
而ASP.NET的session是类似服务端的一种存储数据的模式。它是通过客户端cookie和uri来维护session的

1. 利用ASP.NET的session实现认证,在aspx里记录用户认证信息:

string UserId = HttpContext.Current.User.Identity.Name; 
int Timeout = HttpContext.Current.Session.Timeout

2. 如果WCF服务端能够共享Asp.NET的session,必须在WCF配置文件中进行如下设置:

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"  />
3.在服务端新建一个用户类:

public static class UserHelper
    {
        public  const string SessionUserKey = "Session_Current_User";

        /// <summary>
        /// 取得当前用户信息
        /// </summary>
        public static UserInfo CurrentUser
        {
            get
            {
                if (!HttpContext.Current.User.Identity.IsAuthenticated)
                {
                    HttpContext.Current.Response.Redirect(System.Configuration.ConfigurationManager.AppSettings["LogoutRedirectUrl"]);
                    return null;
                }

                string key = SessionUserKey;
                object user = null;

                if(HttpContext.Current.Session != null)
                    user = HttpContext.Current.Session[key];

                if (user == null)
                {
                    var info = new AdminService().GetUserById(HttpContext.Current.User.Identity.Name); // 获取用户信息
                    HttpContext.Current.Session[key] = info;
                    return info;
                }
                return (UserInfo)user;
            }
            set { HttpContext.Current.Session[SessionUserKey] = value; }
        }
}
4. 在WCF服务端可以利用共享的session来判断权限:

[Serializable]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public partial class AdminService : IAdminService
    {
        public AdminService()
        {
        }
        public string InsertAdmin(Admin admin)
        {
            int errorCount = 0;
            if (!UserHelper.CurrentUser == null)
            {
                CustomerFaultException exception = new CustomerFaultException
                {
                    ExceptionCode = "S001",
                    ExceptionMessage = "没有权限访问,请登录!"
                };
                throw new FaultException<CustomerFaultException>(exception);
            }
            AdminSummary adminSummary = adminDal.GetAdminSummary(admin.UserId, out errorCount);
            if (adminSummary == null)
                return adminDal.InsertAdmin(admin);
            else
                return "1001";
        }
5.在客户端获取sessionId,我们可以通过Cookie获取客户端的sessionId

void InitialInvoke()
        {
            IHelloService proxy = factory.CreateChannel();
            using (new OperationContextScope((IContextChannel)proxy))
            {
                Console.WriteLine(proxy.Greet("Hello"));
                HttpResponseMessageProperty responseProperty = OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name]
                    as HttpResponseMessageProperty;
                helper = HttpSessionCookieHelper.Create((string)responseProperty.Headers[HttpResponseHeader.SetCookie]);
            }

            ((IClientChannel)proxy).Close();
        }
httpSessionCookieHelper是从cookie中获取sessionId的(CookieName 是“ASP.NET_SessionId”)

class HttpSessionCookieHelper
        {
            const string AspNetSessionIdCookieName = "ASP.NET_SessionId";
            string aspNetSessionId = string.Empty;
            HttpSessionCookieHelper()
            { }

            public static HttpSessionCookieHelper Create(string cookieString)
            {
                HttpSessionCookieHelper helper = new HttpSessionCookieHelper();
                helper.ParseCookieString(cookieString);
                return helper;
            }

            public static HttpSessionCookieHelper CreateFromSessionId(string sessionId)
            {
                HttpSessionCookieHelper helper = new HttpSessionCookieHelper();
                helper.aspNetSessionId = sessionId;
                return helper;
            }

            public void AddSessionIdToRequest(HttpRequestMessageProperty requestProperty)
            {
                if (string.IsNullOrEmpty(this.aspNetSessionId))
                    return;

                string sessionCookieString = string.Format("{0}={1}", AspNetSessionIdCookieName, this.aspNetSessionId);
                string cookieString = (string)requestProperty.Headers[HttpRequestHeader.Cookie];
                if (string.IsNullOrEmpty(cookieString))
                {
                    cookieString = sessionCookieString;
                }
                else
                {
                    cookieString = string.Format("{0}; {1}", cookieString, sessionCookieString);
                }

                requestProperty.Headers[HttpRequestHeader.Cookie] = cookieString;
            }

            void ParseCookieString(string cookieString)
            {
                if (string.IsNullOrEmpty(cookieString))
                    return;

                string[] cookies = cookieString.Split(';');
                for (int i = 0; i < cookies.Length; i++)
                {
                    string[] cookieNameValues = cookies[i].Split('=');
                    if (cookieNameValues[0] == AspNetSessionIdCookieName)
                    {
                        this.aspNetSessionId = cookieNameValues[1];
                        return;
                    }
                }
            }

            public string AspNetSessionId
            {
                get
                {
                    return this.aspNetSessionId;
                }
            }
        }

这样我们可以在第一次调用的回复中获取sessionId

void Invoke2()
        {
            IHelloService proxy = factory.CreateChannel();
            using (new OperationContextScope((IContextChannel)proxy))
            {
                HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty();
                helper.AddSessionIdToRequest(requestProperty);
                OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty;
                Console.WriteLine(proxy.Greet("Howdy"));
            }

            ((IClientChannel)proxy).Close();

            if (Interlocked.Increment(ref completedCount) == 2)
            {
                waitHandle.Set();
            }
        }
注:第5点可以参照:http://blogs.msdn.com/b/wenlong/archive/2010/02/21/using-asp-net-sessions-from-wcf.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: