2011-10-01 3 views
2

질문 :ASP.NET : 쿠키가없는 세션을위한 ISessionIDManager를 구현하고 있습니까?

저는 맞춤 세션 제공자를 만들고 있습니다. 지금까지는 훌륭하게 작동합니다. 세션 ID를 제어하기 위해 사용자 지정된 ISessionIDManager를 추가하기로 결정했습니다.

쿠키 세션에는 이미 잘 작동합니다. 하지만이 같은 쿠키에 Switch가 아래로 내려가 때

<sessionState mode="Custom" customProvider="custom_provider" cookieless="true" timeout="1" 
       sessionIDManagerType="Samples.AspNet.Session.MySessionIDManager" 
       sqlConnectionString="Data Source=localhost;Initial Catalog=TestDB;User Id=SomeUser;Password=SomePassword;" 
       sqlCommandTimeout="10" 
       > 
    <!-- timeout in minutes--> 
    <providers> 
     <add name="custom_provider" type="Test.WebSession.CustomSessionStoreProvider" /> 
    </providers> 
    </sessionState> 

를 그 다음은 리디렉션 :
http://localhost:52897/(77bb065f-d2e9-4cfc-8117-8b89a40e00d8)/default.aspx
이가 HTTP 404 이해

을 던져 왜 그런 폴더가 없기 때문에.
http://localhost:52897/(S(sq2abm453wnasg45pvboee45))/DisplaySessionValues.aspx

을 더 HTTP 404이 없다 ... : 기본 세션 관리자 (하나의 asp.net와 함께 제공)을 사용하고, 쿠키로 전환하면

는하지만 URL은 다음과 같습니다

URL에 대괄호로 묶인 세션 ID에 (S 및)를 추가하려고 시도했지만 도움이되지 않았습니다.


무엇이 누락 되었습니까?

using System; 
using System.Configuration; 
using System.Web.Configuration; 
using System.Web; 
using System.Web.SessionState; 

// http://allantech.blogspot.com/2011/04/cookieless-session-state-in-aspnet.html 
// http://forums.asp.net/t/1082784.aspx/1 

// http://stackoverflow.com/questions/4612310/implementing-a-custom-sessionidmanager 
// http://msdn.microsoft.com/en-us/library/system.web.sessionstate.isessionidmanager.aspx 
// http://msdn.microsoft.com/en-us/library/system.web.sessionstate.isessionidmanager(v=vs.80).aspx 

namespace Samples.AspNet.Session 
{ 

    // Samples.AspNet.Session.MySessionIDManager 
    public class MySessionIDManager : IHttpModule, ISessionIDManager 
    { 

     protected SessionStateSection pConfig = null; 
     internal const string HeaderName = "AspFilterSessionId"; 


     protected void InitializeModule() 
     { 
      // Obtain session-state configuration settings. 
      if (pConfig == null) 
      { 
       Configuration cfg = 
        WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath); 
       pConfig = (SessionStateSection)cfg.GetSection("system.web/sessionState"); 
      } // End if (pConfig == null) 
     } 

     // 
     // IHttpModule Members 
     // 


     // 
     // IHttpModule.Init 
     // 
     public void Init(HttpApplication app) 
     { 
      //InitializeModule(); 
     } // End Sub Init 


     // 
     // IHttpModule.Dispose 
     // 
     public void Dispose() 
     { 
     } // End Sub Dispose 




     // 
     // ISessionIDManager Members 
     // 




     // 
     // ISessionIDManager.Initialize 
     // 
     public void Initialize() 
     { 
      InitializeModule(); 
     } // End Sub Initialize 


     // 
     // ISessionIDManager.InitializeRequest 
     // 
     public bool InitializeRequest(
      HttpContext context, 
      bool suppressAutoDetectRedirect, 
      out bool supportSessionIDReissue 
     ) 
     { 

      if (pConfig.Cookieless == HttpCookieMode.UseCookies) 
      { 
       supportSessionIDReissue = false; 
       return false; 
      } 
      else 
      { 
       supportSessionIDReissue = true; 
       return context.Response.IsRequestBeingRedirected; 
      } 

     } // End Function InitializeRequest 





     // 
     // ISessionIDManager.GetSessionID 
     // 
     public string GetSessionID(HttpContext context) 
     { 
      string id = null; 

      if (pConfig.Cookieless == HttpCookieMode.UseUri) 
      { 
       string tmp = context.Request.Headers[HeaderName]; 
       if (tmp != null) 
        id = HttpUtility.UrlDecode(id); 

       // Retrieve the SessionID from the URI. 
      } 
      else 
      { 
       if (context.Request.Cookies.Count > 0) 
       { 
        id = context.Request.Cookies[pConfig.CookieName].Value; 
        id = HttpUtility.UrlDecode(id); 
       } 
      } 

      // Verify that the retrieved SessionID is valid. If not, return null. 

      if (!Validate(id)) 
       id = null; 

      return id; 
     } // End Function GetSessionID 


     // 
     // ISessionIDManager.CreateSessionID 
     // 
     public string CreateSessionID(HttpContext context) 
     { 
      return System.Guid.NewGuid().ToString(); 
     } // End Function CreateSessionID 


     // 
     // ISessionIDManager.RemoveSessionID 
     // 
     public void RemoveSessionID(HttpContext context) 
     { 
      context.Response.Cookies.Remove(pConfig.CookieName); 
     } // End Sub RemoveSessionID 



     public static string InsertSessionId(string id, string path) 
     { 
      string dir = GetDirectory(path); 
      if (!dir.EndsWith("/")) 
       dir += "/"; 

      string appvpath = HttpRuntime.AppDomainAppVirtualPath; 
      if (!appvpath.EndsWith("/")) 
       appvpath += "/"; 

      if (path.StartsWith(appvpath)) 
       path = path.Substring(appvpath.Length); 

      if (path[0] == '/') 
       path = path.Length > 1 ? path.Substring(1) : ""; 

      // //http://localhost:52897/(S(sq2abm453wnasg45pvboee45))/DisplaySessionValues.aspx 
      return Canonic(appvpath + "(" + id + ")/" + path); 
      //return Canonic(appvpath + "(S(" + id + "))/" + path); 
     } 


     public static bool IsRooted(string path) 
     { 
      if (path == null || path.Length == 0) 
       return true; 

      char c = path[0]; 
      if (c == '/' || c == '\\') 
       return true; 

      return false; 
     } 


     public static string Canonic(string path) 
     { 
      char[] path_sep = { '\\', '/' }; 


      bool isRooted = IsRooted(path); 
      bool endsWithSlash = path.EndsWith("/"); 
      string[] parts = path.Split(path_sep); 
      int end = parts.Length; 

      int dest = 0; 

      for (int i = 0; i < end; i++) 
      { 
       string current = parts[i]; 

       if (current.Length == 0) 
        continue; 

       if (current == ".") 
        continue; 

       if (current == "..") 
       { 
        dest--; 
        continue; 
       } 
       if (dest < 0) 
        if (!isRooted) 
         throw new HttpException("Invalid path."); 
        else 
         dest = 0; 

       parts[dest++] = current; 
      } 
      if (dest < 0) 
       throw new HttpException("Invalid path."); 

      if (dest == 0) 
       return "/"; 

      string str = String.Join("/", parts, 0, dest); 

      str = RemoveDoubleSlashes(str); 

      if (isRooted) 
       str = "/" + str; 
      if (endsWithSlash) 
       str = str + "/"; 

      return str; 
     } 




     public static string GetDirectory(string url) 
     { 
      url = url.Replace('\\', '/'); 
      int last = url.LastIndexOf('/'); 

      if (last > 0) 
      { 
       if (last < url.Length) 
        last++; 

       return RemoveDoubleSlashes(url.Substring(0, last)); 
      } 

      return "/"; 
     } 


     public static string RemoveDoubleSlashes (string input) 
     { 
      // MS VirtualPathUtility removes duplicate '/' 

      int index = -1; 
      for (int i = 1; i < input.Length; i++) 
      if (input [i] == '/' && input [i - 1] == '/') { 
       index = i - 1; 
       break; 
      } 

      if (index == -1) // common case optimization 
      return input; 

      System.Text.StringBuilder sb = new System.Text.StringBuilder(input.Length); 
      sb.Append (input, 0, index); 

      for (int i = index; i < input.Length; i++) { 
      if (input [i] == '/') { 
       int next = i + 1; 
       if (next < input.Length && input [next] == '/') 
       continue; 
       sb.Append ('/'); 
      } 
      else { 
       sb.Append (input [i]); 
      } 
      } 

      return sb.ToString(); 
     } 



     // http://www.dotnetfunda.com/articles/article1531-how-to-add-custom-headers-into-readonly-httprequest-object-using-httpmodule-.aspx 
     public void SetHeader(string strHeaderName, string strValue) 
     { 
      //get a reference 
      System.Collections.Specialized.NameValueCollection headers = HttpContext.Current.Request.Headers; 
      //get a type 
      Type t = headers.GetType(); 
      //get the property 
      System.Reflection.PropertyInfo prop = t.GetProperty(
        "IsReadOnly", 
        System.Reflection.BindingFlags.Instance 
       | System.Reflection.BindingFlags.IgnoreCase 
       | System.Reflection.BindingFlags.NonPublic 
       | System.Reflection.BindingFlags.FlattenHierarchy 
       | System.Reflection.BindingFlags.NonPublic 
       | System.Reflection.BindingFlags.Public 
       | System.Reflection.BindingFlags.FlattenHierarchy 
      ); 
      //unset readonly 

      prop.SetValue(headers, false, null); // Set Read-Only to false 

      //add a header 
      //HttpContext.Current.Request.Headers.Add(strHeaderName, strValue); 
      //headers.Add(strHeaderName, strValue); 

      t.InvokeMember("BaseAdd", 
        System.Reflection.BindingFlags.InvokeMethod 
       | System.Reflection.BindingFlags.NonPublic 
       | System.Reflection.BindingFlags.Instance, 
        null, 
        headers, 
        new object[] { strHeaderName, new System.Collections.ArrayList { strValue } } 
      ); 

      prop.SetValue(headers, true, null); // Reset Read-Only to true 

      // Victory ! 

      //string strCheckHeaders = string.Join(Environment.NewLine, HttpContext.Current.Request.Headers.AllKeys); 
     } 

     // 
     // ISessionIDManager.SaveSessionID 
     // 
     public void SaveSessionID(HttpContext context, string id, out bool redirected, out bool cookieAdded) 
     { 
      if (!Validate(id)) 
       throw new HttpException("Invalid session ID"); 

      Type t = base.GetType(); 

      redirected = false; 
      cookieAdded = false; 

      if (pConfig.Cookieless == HttpCookieMode.UseUri) 
      { 
       // Add the SessionID to the URI. Set the redirected variable as appropriate. 

       //context.Request.Headers.Add(HeaderName, id); 
       //context.Request.Headers.Set(HeaderName, id); 
       SetHeader(HeaderName, id); 

       cookieAdded = false; 
       redirected = true; 
       UriBuilder newUri = new UriBuilder(context.Request.Url); 
       newUri.Path = InsertSessionId(id, context.Request.FilePath); 

       //http://localhost:52897/(S(sq2abm453wnasg45pvboee45))/DisplaySessionValues.aspx 
       context.Response.Redirect(newUri.Uri.PathAndQuery, false); 
       context.ApplicationInstance.CompleteRequest(); // Important ! 

       return; 
      } 
      else 
      { 
       context.Response.Cookies.Add(new HttpCookie(pConfig.CookieName, id)); 
       cookieAdded = true; 
      } 

     } // End Sub SaveSessionID 


     // 
     // ISessionIDManager.Validate 
     // 
     public bool Validate(string id) 
     { 
      try 
      { 
       Guid testGuid = new Guid(id); 

       if (id == testGuid.ToString()) 
        return true; 
      } 
      catch 
      { 
      } 

      return false; 
     } // End Function Validate 


    } // End Class MySessionIDManager : IHttpModule, ISessionIDManager 


} // End Namespace Samples.AspNet.Session 
+0

나는 너에게 비슷한 것을 시도하고있다. 내 도메인 및 IP (wap proxies ip)에 따라 쿠키 이동 모드를 변경하고 싶습니다. 나는 총 잃어 버렸어. 더 많은 것을 얻습니까? 사전에 미리 – fravelgue

답변

4

처음부터 맞춤 세션 ID 관리자를 만드는 것은 많은 일처럼 보입니다. System.Web.SessionState.SessionIDManager 클래스에서 상속 받고 CreateSessionID 메서드를 재정의하는 방법은 무엇입니까?

public class MySessionIDManager : SessionIDManager, ISessionIDManager 
{ 
    public override string CreateSessionID(HttpContext context) 
    { 
     return System.Guid.NewGuid().ToString("N"); 
    } 
} 
+0

흥미 롭습니다. 일해야한다. 그것은 또한 유효성 검사를 덮어 쓸 필요가 있지만 아무런 문제가되지 않습니다. –

+0

@StefanSteiger'SessionIDManager' 클래스를 사용해 보았습니까? – Kiquenet

0

다른 모든 문제가 해결되지 않으면 Reflector 또는 ILSpy를 사용하여 .NET 구현을 열어 다른 작업을 확인하십시오.

+0

그들은 ISessionIDManager를 구현하지 않고 HTTP 모듈을 구현합니다. –

관련 문제