原文:http://blog.csdn.net/kntao/article/details/6921433
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