How to get SessionID on a request where EnableSessionState="False" - asp.net

I want to be able to get the SessionID of the currently authenticated session in a WebMethod function where EnableSession = false.
I cannot set EnableSession=true on this request, because another (long running) request on a different page is keeping the SessionState locked (EnableSessionState == "True" not "Readonly").
Is there a consistent way of getting the SessionID from either the ASP.NET Session cookie or the Url for cookieless sessions? I can code it myself but I would rather use a function that is already documented and tested.
Thank you very much,
Florin.

There seems to be no ASP.NET function that can do this, so I made up a hack of my own, which works... for now ;):
private string GetSessionID(HttpContext context)
{
var cookieless = context.Request.Params["HTTP_ASPFILTERSESSIONID"];
if (!string.IsNullOrEmpty(cookieless))
{
int start = cookieless.LastIndexOf("(");
int finish = cookieless.IndexOf(")");
if (start != -1 && finish != -1)
return cookieless.Substring(start + 1, finish - start - 1);
}
var cookie = context.Request.Cookies["ASP.NET_SessionId"];
if (cookie != null)
return cookie.Value;
return null;
}

HttpContext.Current.Session.SessionID

Related

Session FROM ASP.NET to classic asp

I have an old system that was developed, not by me, in classic ASP.
I have a new system, developed by me in ASP.NET
How can I pass a session variable (not complex types, just a simple string or int) TO that classic ASP page? I don't need anything back from it.
To add a spanner to the works - how can I do the "hand off" or transfer if the classic ASP site is on a different domain?
Update:
Cannot use the option of passing items via querystring OR storing it in a DB and letting the classic ASP read it from the DB.
Thank you
you could use a classic asp page that sets session variables out of e.g. post parameters.
then call that classic asp page from your asp.net page.
example (not complete) session.asp:
if session("userIsloggedIn") = true and request.form("act") = "setSessionVar" then
session(request.form("name")) = request.form("value")
end if
of course this is some kind of hack but we are talking about classic asp...
I had a different direction. I exchanged the session states via a cookie. Adding these methods. So now instead of calling Session directly, I use these methods instead.
ASP.NET
public static void AddSessionCookie(string key, string value)
{
var cookie = HttpContext.Current.Request.Cookies["SessionCookie"];
if (cookie == null)
{
cookie = new HttpCookie("SessionCookie");
cookie.Expires = DateTime.Now.AddHours(12);
HttpContext.Current.Response.Cookies.Add(cookie);
HttpContext.Current.Request.Cookies.Add(cookie);
}
HttpContext.Current.Session[key] = value;
cookie[key] = value;
}
public static string GetSessionCookie(string key)
{
if (HttpContext.Current.Session[key] == null)
return string.Empty;
string cook = HttpContext.Current.Session[key].ToString();
if (!String.IsNullOrEmpty(cook))
{
var cookie = HttpContext.Current.Request.Cookies["SessionCookie"];
if (cookie == null)
{
cookie = new HttpCookie("SessionCookie");
cookie.Expires = DateTime.Now.AddHours(12);
HttpContext.Current.Response.Cookies.Add(cookie);
HttpContext.Current.Request.Cookies.Add(cookie);
}
if (cookie != null)
cookie[key] = cook;
return cook;
}
return cook;
}
Then for Classic
Function AddSessionCookie(key, value)
Response.Cookies("SessionCookie")(key)= value
Response.Cookies("SessionCookie").Expires = DATE + 1
Session(key) = value
End Function
Function GetSessionCookie(key)
If Session(key) <> "" Then
Response.Write(Session(key))
ELSEIF Response.Cookies("SessionCookie")(key) <> "" THEN
Session(key)=Response.Cookies("SessionCookie")(key)
Set GetSessionCookie = Session(key)
End If
End Function

Delete cookie from a servlet response

I would like to know how to delete a cookie in an HttpServletResponse in Spring MVC. I have the login method where I create the cookie and the logout where I want to delete it, but it doesn't work.
Here is the code:
#RequestMapping(method = RequestMethod.POST)
public ModelAndView Login(HttpServletResponse response, String user, String pass) {
if (user != null && pass != null && userMapper.Users.get(user).getPass().equals(pass)){
Cookie cookie = new Cookie("user", user);
cookie.setPath("/MyApplication");
cookie.setHttpOnly(true);
cookie.setMaxAge(3600);
response.addCookie(cookie);
Map model = new HashMap();
model.put("user", user);
return new ModelAndView("home", "model", model);
}
return new ModelAndView("login");
}
#RequestMapping(value="/logout", method = RequestMethod.POST)
public ModelAndView Logout(HttpServletRequest request, HttpServletResponse response) {
Cookie[] cookies = request.getCookies();
for(int i = 0; i< cookies.length ; ++i){
if(cookies[i].getName().equals("user")){
//Cookie cookie = new Cookie("user", cookies[i].getValue());
//cookie.setMaxAge(0);
//response.addCookie(cookie);
cookies[i].setMaxAge(0);
response.addCookie(cookies[i]);
break;
}
}
return new ModelAndView("login");
}
I thought it was only needed to change the maxAge, but in the browser the cookie don't change. I even tried to rewrite a cookie with the same name in the commented block but it doesn't work either.
Setting the maximum age to 0 is right. But it must have exactly the same other cookie properties, except of the value. Thus exactly the same domain, path, secure, etc. The value is optional, it can best be set to null.
So, given the way how you created the cookie,
Cookie cookie = new Cookie("user", user);
cookie.setPath("/MyApplication");
cookie.setHttpOnly(true);
cookie.setMaxAge(3600);
response.addCookie(cookie);
it needs to be removed as follows:
Cookie cookie = new Cookie("user", null); // Not necessary, but saves bandwidth.
cookie.setPath("/MyApplication");
cookie.setHttpOnly(true);
cookie.setMaxAge(0); // Don't set to -1 or it will become a session cookie!
response.addCookie(cookie);
That said, I'm not sure how it's useful to store the logged-in user as a cookie. You're basically also allowing the enduser to manipulate its value. Rather just store it as a session attribute instead and call session.invalidate() on logout.
No need to use your own code. Just configure rememberMeServices bean that would create cookie while user' logging in with rememberMe option checked, and would delete it after logout.

Persisting Session to DB

My architect is wondering why we need to persist each user's session to the DB instead of just using cookies. I have never seen anyone use just cookies.
Usually I hold the Session Id in a cookie then use it to perform CRUDS on the session record keyed off the ID.
I mean I don't see how you can do session state without in proc. I've always done session state via a custom table holding routine fields like IsLoggedIn, IsClosed, IsNew, IPAddress, Browser, and so on.
Has anyone done session state on an e-commerce site without persisting it in a DB?
UPDATED
So here is kinda how we did things at another place I worked for an e-commerce site that got 500+ page hits a month:
public USession CreateNewSession(int userID)
{
string ipAddress = GetCurrentRequestIPAddress(context.Request);
USession newSession = USession.NewSession();
newSession.IpAddress = ipAddress;
newSession.UserID = customerID;
newSession.Browser = context.Request.UserAgent ?? string.Empty;
if (context.Request.UrlReferrer != null)
newSession.Referer = context.Request.UrlReferrer.ToString();
else
newSession.Referer = string.Empty;
InsertSession(newSession);
return newSession;
}
public USession CreateNewSession(int userID)
{
string ipAddress = GetCurrentRequestIPAddress(context.Request);
USession newSession = USession.NewSession();
newSession.IpAddress = ipAddress;
newSession.UserID = customerID;
newSession.Browser = context.Request.UserAgent ?? string.Empty;
if (context.Request.UrlReferrer != null)
newSession.Referer = context.Request.UrlReferrer.ToString();
else
newSession.Referer = string.Empty;
InsertSession(newSession);
return newSession;
}
public USession GetSession()
{
// existing sessionId this session?
HttpCookie cookie = context.Request.Cookies["usessionId"];
if (cookie == null || string.IsNullOrEmpty(cookie.Value))
session = CreateNewSession(0);
else
{
string sessionID = cookie.Value;
session = GetSession(sessionID);
if (session == null)
session = CreateNewSession(0);
else if (session.IsClosed > 0)
session = CreateNewSession(session.UserID);
}
if (session.LastAccessed < DateTime.Now.AddHours(-1)) session.LoggedIn = false;
if (session.LastDestination.Equals("lesson"))
session.LastDestPageDestinationID = ContextValue(context, "lessonid");
else
session.LastDestPageDestinationID = 0;
if (session.IsNew) session.FirstDestination = session.LastDestination;
SaveSession();
return session;
}
private void SaveSession()
{
session.LastAccess = DateTime.Now;
session.LastDest = string.Empty;
db.UpdateSession(session);
if (!cookieIsSet)
{
// add a session cookie for this current session
HttpCookie cookie = CreateSessionCookie("usessionId", session.SessionID, 365);
if (session.LastDest.Equals("logout", StringComparison.OrdinalIgnoreCase))
cookie.Value = string.Empty;
if (session.LastDest.Equals("lessonOrder")) return;
context.Response.SetCookie(cookie);
}
}
internal void UpdateSession(USession s)
{
using (ourConnection conn = CreateConnection("UpdateSession"))
{
conn.CommandText = #"update csession set
closed = #closed,
userID = #customerID,
lastAccess = #lastAccess,
lastDestination = #lastDest,
orderId = #OrderId,
IsloggedIn = #isLoggedIn;
conn.AddParam("#id", s.Id);
conn.AddParam("#closed", s.Closed);
conn.AddParam("#userID", s.UserID);
conn.AddParam("#lastAccess", s.LastAccess);
conn.AddParam("#firstDestination", s.FirstDestination);
conn.AddParam("#lastDestination", s.LastDestination);
conn.AddParam("#isLoggedIn", s.IsLoggedIn);
conn.AddParam("#orderID", s.OrderID);
try
{
conn.ExecuteNonQuery();
}
catch (Exception ex)
{
LogException(ex);
}
}
}
public HttpCookie CreateSessionCookie(string cookieValue, string uSessionID, double daysTillExpiration)
{
HttpCookie cookie = new HttpCookie("usessionid", uSessionID);
cookie.Expires = DateTime.Now.AddDays(daysTillExpiration);
cookie.Path = "/";
return cookie;
}
So we'd work with the USession custom object in memory throughout our code for checking for loggedIn, to force close their session, and all sorts of stuff based on their current session.
Also in our Application_Error in global.asax we would log the current sessionId for tracking purposes on error.
HttpCookie cookie = Request.Cookies["usessionid"];
if (cookie != null)
{
logger.Variables = "<b>uSessionID:</b> " + cookie.Value;
if (cookie.Value.Length > 0)
logger.USessionID = GetUSessionID(cookie.Value);
}
The ASP.NET session has 3 possible states:
Off (my preferred) - don't use any session at all
InProc - the session is stored in the memory of the web server. Fast, but not convinient if you are running in a web farm because each node of the web farm will have a different copy of the session and you might get conflicts.
Out-of-Proc - the session is stored in memory of a specially dedicated server running the ASP.NET Session state Windows service. Good for webfarms scenarios but not reliable enough as the session is still persisted in the memory of some server which might not survive crashes.
SQL Server - the session is persisted in SQL server. Very reliable and suitable for web farms. Problem is with performance. It will be slower than the previous modes as the session is now persisted in the database.
The 3 modes are covered in depth in the following article.
The mode you choose is configured in web.config and it is completely transparent to your code in which you simply use the Session["someKey"] to work with the session, it's just the underlying storage mechanism that differs.

How to determine Session Timeout using when reusing CookieContainer

I have the following code which re-uses a CookieContainer which logs in on the first request, but just uses the cookie container for requests after.
After a period of time if idle the site will give a Session Timeout, I will need to perform the login again.
Q: Can I determine (with the cookie container object) if the timeout has happened or is it best to determine if it has happened from the HttpWebResponse which happens to contains text like 'session timeout'. What is the best way to do this?
private static CookieContainer _cookieContainer;
private static CookieContainer CurrentCookieContainer
{
get
{
if (_cookieContainer == null || _cookieContainer.Count == 0)
{
lock (_lock)
{
if (_cookieContainer == null || _cookieContainer.Count == 0)
{
//_cookieContainer.GetCookies(
_cookieContainer = DoLogin();
}
}
}
return _cookieContainer;
}
set
{
_cookieContainer = value;
}
}
And then this method calls out to the container:
public static string SomeMethod(SomeParams p)
{
HttpWebRequest request_thirdPartyEnquiryDetails = (HttpWebRequest)WebRequest.Create(thirdPartyEnquiryDetails);
CookieContainer cookieContainer = CurrentCookieContainer;
request_thirdPartyEnquiryDetails.CookieContainer = cookieContainer;
//... and it goes on to submit a search and return the response
}
Well, since the timeout is 30 mins, I have set the login to repeat after 25 mins.
private static DateTime? lastLoggedIn;
private static CookieContainer _cookieContainer;
private static CookieContainer CurrentCookieContainer
{
get
{
if (_cookieContainer == null || _cookieContainer.Count == 0 || !lastLoggedIn.HasValue || lastLoggedIn.Value.AddMinutes(25) < DateTime.Now)
{
lock (_lock)
{
if (_cookieContainer == null || _cookieContainer.Count == 0 || !lastLoggedIn.HasValue || lastLoggedIn.Value.AddMinutes(25) < DateTime.Now)
{
_cookieContainer = DoLogin();
lastLoggedIn = DateTime.Now;
}
}
}
return _cookieContainer;
}
set
{
_cookieContainer = value;
}
}
As an extra precaution, I check the HttpResponse for the text which returns when the page session times out (although its now expected this won't be seen). If this happens I set the lastLoggedIn date to null and run the search method again.
You can extract all cookies for a domain using the CookieContainer.GetCookies(string uri) method. Using this CookieCollection you can get the cookie you are interested in and check its Expired property to see if it has expired.
There is one thing you should note: Your session may end even if your cookie is valid. IIS may restart the app domain the web application runs in and in that case all authenticated users may loose their session data. So checking the cookie is generally not enough to ensure that you stay logged in.
I am not sure what you want to achieve, but you should notice that CookieContainer has a bug on .Add(Cookie) and .GetCookies(uri) method.
See the details and fix here:
http://dot-net-expertise.blogspot.com/2009/10/cookiecontainer-domain-handling-bug-fix.html

Best way to determine if cookies are enabled in ASP.NET?

What is the best method for determining if a users browser has cookies enabled in ASP.NET
Set a cookie, force a redirect to some checking page and check the cookie.
Or set a cookie on every pageload, if it's not already set. For instance, I assume this is to check if cookies are supported to display a message when they try to login that they need to enable cookies. Set your login cookie to some default value for guest users if they don't have the cookie set yet. Then on your login page, check for the user cookie, and if it's not set, then display your message.
#Mattew is right the only way to find out is to set a cookie, redirect, then check it.
Here is a C# function to preform that check you can put this in your page load event:
private bool cookiesAreEnabled()
{
bool cookieEnabled = false;
if(Request.Browser.Cookies)
{
//Your Browser supports cookies
if (Request.QueryString["TestingCookie"] == null)
{
//not testing the cookie so create it
HttpCookie cookie = new HttpCookie("CookieTest","");
Response.Cookies.Add(cookie);
//redirect to same page because the cookie will be written to the client computer,
//only upon sending the response back from the server
Response.Redirect("Default.aspx?TestingCookie=1")
}
else
{
//let's check if Cookies are enabled
if(Request.Cookies["CookieTest"] == null)
{
//Cookies are disabled
}
else
{
//Cookies are enabled
cookieEnabled = true;
}
}
}
else
{
// Your Browser does not support cookies
}
return cookieEnabled;
}
You can do it in javascript also, this way :
function cookiesAreEnabled()
{
var cookieEnabled = (navigator.cookieEnabled) ? 1 : 0;
if (typeof navigator.cookieEnabled == "undefined" && cookieEnabled == 0){
document.cookie="testcookie";
cookieEnabled = (document.cookie.indexOf("test­cookie") != -1) ? 1 : 0;
}
return cookieEnabled == 1;
}
Write a cookie, redirect, see if you can read the cookie.
Well I think if we can save cookie in Global.ASAX session start and read that on page.. isnt that best way?
Essentially the same solution as meda, but in VB.NET:
Private Function IsCookieDisabled() As Boolean
Dim currentUrl As String = Request.RawUrl
If Request.Browser.Cookies Then
'Your Browser supports cookies
If Request.QueryString("cc") Is Nothing Then
'not testing the cookie so create it
Dim c As HttpCookie = New HttpCookie("SupportCookies", "true")
Response.Cookies.Add(c)
If currentUrl.IndexOf("?") > 0 Then
currentUrl = currentUrl + "&cc=true"
Else
currentUrl = currentUrl + "?cc=true"
End If
Response.Redirect(currentUrl)
Else
'let's check if Cookies are enabled
If Request.Cookies("SupportCookies") Is Nothing Then
'Cookies are disabled
Return True
Else
'Cookies are enabled
Return False
End If
End If
Else
Return True
End If
End Function
meda's c# function works though you have to change the line:
HttpCookie cookie = new HttpCookie("","");
to
HttpCookie cookie = new HttpCookie("CookieTest","CookieTest");
You can also check the value of Request.Browser.Cookies. If true, the browser supports cookies.
this is the best way
taken from
http://www.eggheadcafe.com/community/aspnet/7/42769/cookies-enabled-or-not-.aspx
function cc()
{
/* check for a cookie */
if (document.cookie == "")
{
/* if a cookie is not found - alert user -
change cookieexists field value to false */
alert("COOKIES need to be enabled!");
/* If the user has Cookies disabled an alert will let him know
that cookies need to be enabled to log on.*/
document.Form1.cookieexists.value ="false"
} else {
/* this sets the value to true and nothing else will happen,
the user will be able to log on*/
document.Form1.cookieexists.value ="true"
}
}
thanks to Venkat K

Resources