When the user logs in, I want to store his userID in the session with
HttpContext.Current.Session["UserID"] = 2354; (this is just a hard-coded example)
Then, when I run a page method, if I do
var test = HttpContext.Current.Session["UserID"];
will the variable test hold the value I stored when he logged in?
If this is a correct way of doing it, how do I access the session when I receive a call from a page method? I want to put the test =... line in a page method to identify which user the request is coming from.
Thanks.
As has been already answered, yes - it should be fine, though if you sit on a page too long before calling a service using this method [WebMethod] it will fail. Best practice in that case is to check for the session and rebuild as necessary. The same is true for any other authentication to ensure that they haven't become unsyncronized or expired.
[WebMethod(EnableSession = true)]
HttpContext context = HttpContext.Current;
if (context.Session["UserID"] == null) {
Utilites.PopulateSessionVars(context.Request.ClientCertificate, context.Request.ServerVariables["REMOTE_ADDR"]);
}
String userId = context.Session["UserID"].ToString();
(where Utilities.PopulateSessionVars is a method to rebuild the session data off of whatever you're using to log in ... which in my case is a PKI certificate)
Yes, that should work. However, session and forms authentication timeouts are on different timers and have different default timeouts so you cannot guarantee that value in session will be available for the time period during which the user is authenticated if you are using forms authentication.
This should do it
//Note: this code hasn't been tested. Correct me if I'm wrong
//To Set:
if (Session["UserId"] == null)
Session["UserId"] = "12345";
//To Get it:
if (Session["UserId"] != null)
MyObject.Id = Session["UsedId"].ToString();
Yes, but its advisable to do a test straight after your test variable assignment to make sure that the UserID was set correctly before you try to use it.
EDIT
You could try:
var test;
if (HttpContext.Current.Session["UserID"] != null)
{
test = HttpContext.Current.Session["UserID"];
}
Global.asax runs at the application level. You want the user sessions which is a differet http context. Initialize the Session in the home/default login page instead.
Related
I can't really understand the concept of this.
Take a look what I have:
#PostMapping("/login")
public ModelAndView login( #ModelAttribute UserLoginDTO userDto, HttpSession session) {
if (authenticateService.loginCheck(userDto.getUsername(), userDto.getPassword())) {
session.setAttribute("sessionid",123);
return new ModelAndView("redirect:/profile");
} else {
return new ModelAndView("signin","error","Invalid username or password combination, or the user does not exist.");
}
}
I have set a sessionID to the session. When the user navigates around the website, how do I know that it is the same user?
Do I have to store the sessionID on server side in a ConcurrentHashMap?
And when there is a page switch I should do this?
if (conHashMap[...] == session.getId()) {...}
else //redirect to login page
Also on logout, do I just remove the element from the hashmap and call for session.invalidate()?
Or is there a way of doing this without using hashmaps at all?
You know the session is from the same user if the id is the same, yes.
You can eventually store informations on the session. Alternativelly, you can create session scoped beans :
#Component
#Scope(value="session")
public class MyComponent {
// ...
}
All you will store in this kind of objects are only accessible by one user.
Figured it out.
After invalidating, the browser will visit the site with a new session. The new session won't have the "sessionid" attribute bound to it. This way, I could determine which session is a valid one, without using hashmaps.
if (session.getAttribute("sessionid")==null){
return new ModelAndView("signin","error","Session expired, please log in again.");
I dunno whether I described my question well but I'm trying to send some element to other page either with a hyperlink or a Response.Redirect() and it's a key which make some access to the DB so I don't want to send it via url and get it. what should I do? thanks.
You can store it in session, or you could use some type of encoding and pass it in the QueryString.
Another option would be to store the value in ViewState and use Server.Transfer to direct the user to the other page. With Server.Transfer you'll still be able to access the ViewState from the other page like this:
private string ValueFromOtherPage
{
get
{
if (ViewState["value"] != null)
{
return ViewState["value"].ToString();
}
else
{
string value;
if (Context.Handler != null)
{
value = (Context.Handler as PreviousPageName).MyStoredValue;
ViewState["value"] = value;
}
return value;
}
}
}
Take a look at this article for encoding/encrypting the QueryString:
http://www.codeproject.com/KB/web-security/QueryStringEncryptionNET.aspx
You can use session variables to store objects:
Session["VariableName"] = yourObject;
Note that overusing these session variables may lead to memory leaks.
You can save it in a session
You can send a GUID which represent some info (in the QS)
You can use cookies.
I am working on a small webapp for fun, using just Java Servlets at the moment. I have two pages, test1 and test2. At the moment I am creating a new session in test1 like this:
HttpSession session = request.getSession(true);
if (session.isNew() == false) {
session.invalidate();
session = request.getSession (true);
}
In test2 I am retrieving the session like so:
HttpSession session = request.getSession(false);
if (session == null) {
throw new ServletException ("No session.");
}
So the problem is that if I go to test2 first, I am always getting a valid session because the browser creates one. I want to restrict the flow from test1 to test2 so that I have to go to test1 first. My plan is to eventually create a login page that will create the session, but the problem I am seeing here would still be present.
How should I handle this? I would like any ideas to not include 3rd party libraries. I'm doing this as a learning exercise.
Thanks!
This makes no sense. Forget the request.getSession(boolean). Just get the session by request.getSession() and never worry about the nullness/validness.
If you want to pass data through session attributes, then just do in test1:
request.getSession().setAttribute("test", "foo");
and in test2 (which is of course requested in the same session after test1):
String test = (String) request.getSession().getAttribute("test"); // Returns "foo".
As to using the session to check the logged-in User, just do something like in the login code:
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user);
} else {
// Show error?
}
and then in a Filter which is mapped on a url-pattern which represents the restricted area, just check if the User is present or not:
if (((HttpServletRequest) request).getSession().getAttribute("user") != null) {
chain.doFilter(request, response); // Just continue.
} else {
((HttpServletResponse) response).sendRedirect("login"); // Not logged-in, redirect to login page.
}
and when you logout, you just remove the User from the session:
request.getSession().removeAttribute("user");
// Or, more drastically:
request.getSession().invalidate();
Alternatively you can also take a look for declarative Container Managed Security with help of some simple entries in web.xml and the server.xml. This way you don't need to hassle with login/filter logic yourself.
See also:
How do servlets work? Instantiation, sessions, shared variables and multithreading
How to handle authentication/authorization with users in a database?
Authentication filter and servlet for login
If you want to restrict the flow to ensure that test1 comes before test2, have test1 put an attribute value in the session that says it's been visited, and test for that attribute value in test2. If the value is not there, have test2 redirect to test1.
In test1, do this:
HttpSession session = request.getSession();
session.setAttribute("test1",true);
Then, in test2, you can do this:
HttpSession session = request.getSession();
if (session.getAttribute("test1") == null){
response.sendRedirect("test1");
return;
}
A session is just a basket that starts out empty. The concept of whether a user is authenticated or not is separate from whether or not the user has a session.
Java EE and the servlet specifications handle all the login stuff for you, redirecting to login pages and so on. Read up on the built-in capabilities of Java EE. Maybe start here.
When someone login with right credentials set a secession with this
request.getSession().setAttribute("user", "user");
now, you can check in this session user already present or not with this
if (((HttpServletRequest) request).getSession().getAttribute("user") != null)
and you can delete the session at the time of logout
request.getSession().invalidate();
this work perfectly
NOTE:
import HttpServletRequest and pass request parameter like this
import javax.servlet.http.HttpServletRequest;
public home(HttpServletRequest request){}
The users of my web application may have more than one browser window (or tab) open and pointed to the same page. We're using cookie based session id's, and the user will usually work within the same session id in both browsers/tabs. I would like to be able to uniquely identify which browser window (and tab) that requested an ASP.NET page (in order to make sure, that data stored in the session does not get mixed up).
(e.g. I would be happy if the browser would generate and send a window/tab-id with the http request, as it publishes HTTP_USER_AGENT)
Any ideas?
--thomas
If I was going to implement something like this I would probably start with a Dictionary<Type, List<Guid>> and store this in the users session. I would also probably make this be a custom type that delegates the dictionary and have a factory method that works similar to
public Guid GeneratePageIdentifier(Page thepage)
{
var guid = Guid.New();
if(_dictionary[thepage.GetType()] == null)
_dictionary[thepage.GetType()] = new List<Guid> { guid };
else
((List<Guid>)_dictionary[thepage.GetType()]).Add(guid);
return guid;
}
Then embed the guid that's returned from that method on the VIewState of the page. On your page methods that execute actions that you need to validate which page it is you would be able to validate that guid is inside the collection do something. You might also want to implement a custom a type with a guid property to enscapulate more information about why you're doing this or what you need for it to be meaningful.
The Viewstate on each page will be different, maybe you can use some kind of unique identifier created on every page loaded?
It is by default not possible due to the stateless nature of the web, but you could add a "page identifier" that gets generated with each opened page and transmitted for every action.
I'd recommend that you refactor the application in a way that those mixups can't happen, no matter from which page/tab/window the request originates.
As Mark Redman said, you can use Viewstate + Session in order to store values specific to the page.
ViewState is good for storing the key (string), Session for storing whatever type of complex objects.
Use the ViewState or a hidden field in order to load at the first call a GUID.
public string PageUid
{
get
{
if (ViewState["UID"] == null)
ViewState.Add("UID", Guid.NewGuid().ToString());
return ViewState["UID"].ToString();
}
}
Then use the session to get/set your values using this key:
string MyPagesessionVariable
{
get
{
if (Session["MYVAR" + PageUid] == null)
{
Session["MYVAR" + PageUid] = "VALUE NOT SHARED WITH OTHER TABS/WINDOWS";
}
return Session["MYVAR" + PageUid];
}
set
{
Session["MYVAR" + PageUid] = value;
}
}
simple question...
Given I have an ASP.NET site, which uses a [custom] RoleProvider,
Is there any way in which I can somehow "refresh" the provider without forcing the user to log out of the site and log back in?
I'm looking for something that would be akin to a fictional method
Roles.Refresh()
Specifically, I am looking at this for if an administrator changes a user's roles, the user sessions could maybe refresh themselves every 10 minutes or something.
I assume you have something like this in your web.config:
<roleManager enabled="true" defaultProvider="..."
cacheRolesInCookie="true">
The roles are cached in a cookie , so you can force them to refresh by deleting the cookie. This method worked for me. I added the cookieName attribute so that I don't rely on asp.net's default. For your scenario, though, you may be able to just set the cookieTimeout attribute to something reasonable and be done with it.
This method won't update the roles immediately, of course. They will be updated on the next page load after you delete the cookie.
Refresh just need to delete the cookie:
For C#: Roles.DeleteCookie(); // Works as Roles.Refresh()
If you don't want to use cookies you can use Session object to cache the roles.
like this:
public override string[] GetRolesForUser(string username)
{
System.Web.SessionState.HttpSessionState Session = HttpContext.Current.Session;
if (Session["roles"] == null)
Session["roles"] = MyDataProvider.Security.GetRolesForUser(username);
return (string[])Session["roles"];
}
When you need to update the roles for this user you can do
Session["roles"] = null
depend on the custom role provider used.
Just call a "update my role" function on every request? (bad way but at least your sure to update it)
The roles are cached in a cookie (encrypted of course). The simplest solution will be to disable caching in the web.config file. You will loose some performance.
Else you must somehow resend the auth cookie. One major problem is that many browsers will not accept cookies on redirects with method post.
The other solution that worked for me:
1) In a aspx methodod log the user out and store the username in the session
//Add User to role reviewer and refresh ticket
Roles.AddUserToRole(User.Identity.Name, Constants.ROLE_REVISOR);
FormsAuthentication.SignOut();
FormsAuthentication.SetAuthCookie(User.Identity.Name, false); //Might work in some browsers
Session["REFRESHROLES"] = User.Identity.Name;
Response.Redirect("someprotectedurl?someid=" + someid);
2) In the loginpage sign the user in again if username is stored in session
protected void Page_Load(object sender, EventArgs e)
{
string returnUrl = Request.QueryString["ReturnUrl"];
if(String.IsNullOrEmpty(returnUrl) == false)
{
if(Session["REFRESHROLES"] != null)
{
if(!string.IsNullOrEmpty(Session["REFRESHROLES"].ToString()))
{
FormsAuthentication.SetAuthCookie(Session["REFRESHROLES"].ToString(), false);
Session.Remove("REFRESHROLES");
Response.Redirect(returnUrl);
return;
}
}