I need to implement simple servlet user authentication (in Java Dynamic Web Project) but there are things that confuse me quite a bit.
Firstly, the servlet for some reason creates the cookie JSESSIONID although I never ask it to. And moreover, I cannot change its value, if I do request.addCookie(new Cookie("JSESSIONID", session.getId())), it makes something like this:
Cookie: JSESSIONID=6B5B441038414B4381EDB7470018F90E; JSESSIONID=7890D45DF445635C49BDEB3CADA8AD99; .......
so, it duplicates the cookie.
Secondly, I'm not sure where to compare cookie and session's id, and where and how to create session correctly (i.e. request.getSession(true? / false? / nothing?);)
I've read some documentation but still need help.
I have the servlet HomeServlet which shoud redirect user to authentication page if the user is not authenticated.
Here's how I do that (HomeServlet.java):
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(request.getSession().getAttribute("user") != null) {
request.getRequestDispatcher("/WEB-INF/index.jsp").forward(request, response);
} else {
response.sendRedirect("authentication");
}
}
And I also have AuthServlet which serves jsp page with authentication forms and validates users.
AuthServlet.java:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("ACTION");
if ("login".equals(action)) {
String[] result = doSomeValidations();
if (result.size() > 0) { // show validation errors
request.setAttribute("errorLoginMessage", result);
request.setAttribute("email", email);
doGet(request, response);
} else { // authenticate user
request.getSession().setAttribute("user", userObject);
request.getRequestDispatcher("/WEB-INF/index.jsp").forward(request, response);
}
} else if ("signup".equals(action)) {
// ...........................
} else {
doGet(request, response);
}
}
So, could you help me with understanding that? How do I implement user authentication and keep the user logged in throughout the session?
Firstly, the servlet for some reason creates the cookie JSESSIONID
although I never ask it to
HttpSession jsession = request.getSession();
you are requesting a session here and JSESSIONID cookie is created by the container in response
how to create session correctly request.getSession(true? / false? / nothing?);
request.getSession() and request.getSession(true) are exactly the same they start a new session if needed ,but request.getSession(false) means if there is already a session use it but if there isn't don't start one.
How and where you want to start the session is dependent entirely on your requirements
response.addCookie(new Cookie("JSESSIONID", jsession.getId()));
you are not suppossed to add a JSESSIONID cookie yourself , the container will do it for you .
Also you should create session once in your app , once the JSESSIONID cookie is stored in the user's browser(provided cookies are enabled) ,it will be sent along with the request.
How do I implement user authentication
Highly subjective and depends on requirements , you can read this https://docs.oracle.com/cd/E19226-01/820-7627/bncby/index.html
keep the user logged in throughout the session
Your session cookies will help you with that once the user has been authenticated ,as an example login to facebook and keep your cookies tab open
Related
While working on a Java Servlet Filter to integrate with an internal SSO I struggled to find the correct way to create a persistent login using programmatic security functions. Specifically, after reading many tutorials such as this I was calling request.login(username,password) and a user Principal was created that returned correct values for methods request.isUserInRole(role) etc. for the current request.
I expected this to be persistent for the user, but subsequent requests would return null for request.getUserPrincipal() so my authentication code was entered on every request. What I found here after much searching was that calling request.getSession(true) before calling request.login(username,password) causes the Principal to be persistent for the user session.
Is it required to explicitly create a session before logging the user in to persist the Principal for the session? This behaviour seems odd to me so I am wondering if I am doing something wrong. I appreciate any insight from developers more knowledgeable on the matter than myself. Using JDK 7 and Tomcat 8. Realm is an extension of RealmBase that overrides authenticate(username,password), getName(), getPassword(username) and getPrincipal(username).
public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
if(request.getUserPrincipal() == null) {
try {
String userName = request.getParameter(userNameField);
String password = request.getParameter(passwordField);
request.getSession(true); // <-- block always entered without this
request.login(username,password);
}
catch(ServletException e) {
// Handle failed login...
return;
}
}
fc.doFilter(req,res);
}
The answer is in the Tomcat source for AuthenticatorBase.java where the login(username,password) chaining calls the configured Realm's authenticate(username,password) method and then calls register(...) passing the returned Principal and stores it in a session if one exists.
I'm new in the Java world. I am trying to develop an ACME Demo using a simple CSV file as a database to validate user names and passwords. I wonder if it is possible to make some hyperlinks on the index.jsp page, which will take you to other jsp pages of the same website if you click them. As far as I know hyperlinks will invoke the doGet method inside the servle, where -in my case- you gonna be redirected to those secure jsp if your credentials are valid of course. So it has worked for just one hyperlink and I would like to make things more dynamic no matter how many links are there??!!
jsp
Content1
<!-- Here I would like to add more links -->
Servlet
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
processRequest(request, response);
//response.sendRedirect("login.jsp");
HttpSession session= request.getSession(true);
if ((session.getAttribute("userSession") != null) && (session.getAttribute("userSession").equals(session.getId())))
{
response.sendRedirect("content1.jsp");
// How can my doGet method manage multiple links here?
}
else
{
response.sendRedirect("login.jsp");
}
}
You should use a servlet filter.
A filter is a component that will be invoked for all the requests to a given url-mapping, and/or for all the requests to a given servlet.
The filter can then check if the user is logged in. If he's loged in, it asks the container to proceed, i.e. invoke the target servlet as if there was no filter. If he's not logged in, the filter can return an error, or redirect to a login page, or do whatever it wants.
See http://www.oracle.com/technetwork/java/filters-137243.html for an introduction and examples of servlet filters.
I'm new to the use of jsp's, servlets, beans etc ... .
Maybe a strange question, but what is the safest way to make a selection menu in a jsp, to make sure you can't access it directly.
At this moment I have a login system and depending of the "kind" of user I retrieve from the db I send them to a specific jsp depending on the "permissions" they have. On this page they will get a selection of the possibilities they can do.
but if I use something like:
next option
it would be easy to just access these next pages from the outside (not much use for the login system then).
I can use a bean I retrieve from the previous page that I check if it's null (this would be so if you get directly to this page) or something like that.
Any suggestions would be welcome. thx
You can use a Servlet Filter to validate if the user has logged in the system and to verify if the user has the rights to access to this page. An example would be as stated in StackOverflow Servlet-Filters wiki. Posting the relevant code:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
//session.getAttribute("user") contains the user info in session
if (session == null || session.getAttribute("user") == null) {
// No logged-in user found, so redirect to login page.
response.sendRedirect(request.getContextPath() + "/login");
} else {
// Logged-in user found, so just continue request.
chain.doFilter(req, res);
}
}
Our application is using Wicket. We're using Wicket's own forms to handle authentication, the main benefits being that the look of the site is kept consistent.
We thought we couldn't do container authentication because our application allows the user to switch authentication mechanisms mid-stream, and Jetty itself was creating quite a bit of friction anyway, just getting simple authentication to work at the container level.
So we ended up implementing authentication via a filter (there are a number of good examples out there.)
Now I have discovered that by doing this, Wicket authentication is slightly broken. What happened was:
Anonymous user would visit the site.
Security filter determines that the user isn't authenticated and redirects to sign-in.
Wicket renders the sign-in page.
User signs in.
Wicket processes the post to the sign-in form and redirects user back.
Security filter determines that the user isn't authenticated and redirects...
I looked inside my subclass of AuthenticatedWebSession, hoping to find some way I could get a hold of the HttpSession and set a session attribute which could then be checked from the filter. However I couldn't for the life of me find a way to do it.
What I resorted to doing was making yet another filter, coded like this:
public class StealWicketUserFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// Nothing to initialise.
}
#Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException
{
filterChain.doFilter(servletRequest, servletResponse);
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
if ("POST".equals(httpServletRequest.getMethod()) &&
"/sign_in".equals(httpServletRequest.getRequestURI())) {
HttpSession session = httpServletRequest.getSession();
ServerUser currentUser = (ServerUser)
session.getAttribute("wicket:webUIServlet:currentUser");
if (currentUser != null) {
session.setAttribute(CombinedSecurityFilter.CURRENT_USER_ATTRIBUTE,
currentUser);
}
}
else if ("/sign_out".equals(httpServletRequest.getRequestURI())) {
HttpSession session = httpServletRequest.getSession();
session.removeAttribute(CombinedSecurityFilter.CURRENT_USER_ATTRIBUTE);
}
}
#Override
public void destroy() {
// Nothing to destroy.
}
}
This of course works (and will continue to work until Wicket change the prefix they store session attributes under.)
I guess what I want to know is whether this is a bad idea and whether there is a "proper Wicket way" to do this sort of thing.
As for the reason we don't use Wicket's authentication alone - the reason is that we wanted to support SPNEGO authentication and potentially other external authentication types.
You can get hold of your HttpSession,albeit through Request and not Session.
What you need is:
WebRequest req = (WebRequest)RequestCycle.get().getRequest();
HttpSession session = req.getHttpServletRequest().getSession();
However I'm pretty sure Wicket authentication isn't broken in such an obvious manner so I'd probably try to find out what is causing this glitch instead.
General question about java servlets and the best way to handle requests. If I hit my doGet method from a remote server request:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
....
<do work here>
....
kill(request);
}
private void kill(HttpServletRequest request) {
//How do I kill the user session here?
}
After I process the request at my end and generate my output to the requester, I want to basically "kill" their session. Currently, that session lingers and thus eats up memory. Then once the max is reached, all other calls are timed out.
I tried creating a HttpSession object using the request object, but got the same results:
HttpSession session = request.getSession();
session.invalidate();
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
is the proper way to go as suggested by the documentation. A new session will be created once the client sends a new request.
You mentioned that your sessions still take up memory. Do you have any other references to those objects on the session?
You also might want to have a look at: Servlet Session behavior and Session.invalidate
you can remove an attribute from a session using
session.removeAttribute("attribute name");
Try with
session = request.getSession(false); // so if no session is active no session is created
if (session != null)
session.setMaxInactiveInterval(1); // so it expires immediatly
If you dont want Session behavior i.e, having state between multiple requests. Why do you want to create/use session at all. Do not create session or do not store anything in the session.
To make sure that your code is not using session, write a request wrapper which will override getSession() methods.
Set a time-out period in web.xml