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){}
Related
Hi I'm using servlet filter to change session ID on every request in order to avoid session fixation. My problem is when the method doFilter ends the application is redirected to login page. I just want to invalidate and create new session, without redirect. I don't have any other filter.
There is my doFilter code:
HttpSession session= httpServletReq.getSession();
if(session!=null){
User u = session.getAttribute("user");
session.invalidate();
HttpSession newSession = httpServletReq.getSession(true);
newSession.setAttribute("user", u);
}
chain.doFilter(req, resp);
The pattern on filter is ***.xhtml**
Why am I getting redirect to login?
Is it ok to change session ID on a filter?
Thanks
change session ID on every request in order to avoid session fixation
You should do exactly that instead of invalidating the session. You can use HttpServletRequest#changeSessionId() for this.
HttpSession session = httpRequest.getSession(false);
if (session != null) {
httpRequest.changeSessionId();
}
chain.doFilter(request, response);
Do note that HttpServletRequest#getSession() defaults to auto-creating the session, so it actually never returns null. You need to explicitly pass false to HttpServletRequest#getSession(boolean).
That said, you don't necessarily need to perform this on every request, it's sufficient to perform that only at the moment when you login the user.
You only need method session.invalidate().
When you call 'session.invalidate()`, the existing session will be invalidated.
so the servlet request will create new session to network.
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.");
Parameters[userName, UserPW] are sent by the user through a home.jsp. These parameters are matched in Login servlet against a stored userInfo Db using JDBC.
In the doPost method I am using if condition tfor authentication as follows
if (rs.next()) {
String refName = rs.getString("UserName");
String refPass = rs.getString("userPW");
if (user.equals(refName) && pw.equals(refPass)) {
out.println("<br>You are In");
RequestDispatcher dispatch= getRequestDispatcher("/SearchFriend.jsp");
dispatch.forward(req, resp);
System.out.println("sucess");
}
When the authentication is successfull, How can i direct the user to a new jsp or servlet where he can input few textboxes and select-options to select few records from the Db table.
its not clear to me that How can I direct the page to a Search.jsp page in above If condition. The Search.jsp is in weBContent folder of Juno.
I am using JDBC with tomcat7. Please help
It is probably not clear , what exactly your requirement are and what you are trying to achieve by looking into the code you have posted.Kindly reframe your question
According to my assumption , you need to redirect the user to the home page when the authentication is successful.
If so, for that you can store the user credential in the session by making a custom filter say SessionFilter implements Filter
HttpSession session = request.getSession();
Store the credenials in the session and if authentication is successful then redirect using :
RequestDispatcher view = request.getRequestDispatcher(/home.jsp);
view.forward(req,resp);
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.
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;
}
}