I have a method that handles request with a URI of "/home". This request is generated upon successful log-in procedure. Here is a little code to support my situation:
<security:form-login login-processing-url="/static/j_spring_security_check"
login-page="/login" authentication-failure-url="/login?login_error=t"
default-target-url="/home"/>
The method body demonstrates what I am attempting to achieve:
String userMail = SecurityContextHolder.getContext().
getAuthentication().getName();
logger.info(userMail);
Person p = userService.retrieveUserByEmail(userMail);
session.setAttribute("person", p);
return "user/home";
This bit is important as the person p is used as data source for other requests.
Now the problem. I don't know if it is the property of Google Chrome, but for some reason the browser remembers the request you've done before log-in and instead of going through /home request after successful log-in procedure, it generates the previous request bypassing this /home gate, resulting in null pointer exception as person p was never set up, as session wasn't populated by /home request.
I know that for other requests I should do validation, but I don't like the idea of letting user generate any request without prior going through /home .
Done with text description and now to explain how I get unwanted behaviour in steps:
ask for request that you know exist such as:
myApp/nameOfSomething/viewThisSomething - you are brought to log-in page as expected(you must be authenticated for request to be accepted)
you enter correct credentials and instead of going to default-target-url="/home"
you are automatically making previous request myApp/nameOfSomething/viewThisSomething without populating session with necessary data and resulting in nullpointer exception.
What else is interesting is that logger shows the mail, so it might be that they are both executed at the same time but /home request is slower - can that happen?
I resolve the situation in other method by checking if null and forcing to go back to /home which works as expected, but I am control freak and don't like when user is doing what he is not intended to do.
Thank You for Your time,
It's not a bug, it's a feature. It's much more user-friendly to let the user go where he wants to go after login than forcing him to go to the home page. He could have bookmarked one of the protected pages, or simply browsed some non-protected pages containing a link to a protected page.
From http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-form-target:
If a form login isn't prompted by an attempt to access a protected
resource, the default-target-url option comes into play. This is the
URL the user will be taken to after successfully logging in, and
defaults to "/". You can also configure things so that the user always
ends up at this page (regardless of whether the login was "on-demand"
or they explicitly chose to log in) by setting the
always-use-default-target attribute to "true"
IMHO, you should keep things as is, but make sure that the required sesion attribute is set once the login is successful, instead of setting this attribute in the home page. This would ensure that every protected page has access to the session attribute, even if the user didn't go to the home page.
You could do this easily by using a custom UsernamePasswordAuthenticationFilter subclass, that sets the appropriate attribute in session once the authentication has succeeded.
Related
Ok, so I have simple website which force user to start from last finished step. Whenever user refresh page he needs to call at application initialization to:
REST /user/{id}/step
This endpoint will tell where user finished. The problem is I am using http only cookie. So I cannot get this {ID} from cookie in javascript.
At the moment I have added additional cookie(NOT http only) named clientId. So application can get his id from cookie, and call to this particular endpoint.
It is working but I feel that it is kinda not best approach. It has few side effects like taking care of clearing this stupid cookie on logout, etc situations.
What is best practice ? I've been thinking about creating additional endpoint which will be used on every application initialization
REST /user/status
// I want to be restfull, so I dont want REST user/logged/step
which will return setCookie clientId="" or setCookie clientId={ID} whenever user is logged or not, in this case I even don't need to care about clearing cookies on frontend side, any ideas?
The problem is I am using http only cookie.
So this http only cookie contains what? I presume a user's session? Then why do you need to specify this user ID in the URL if you should be able to get the ID from the session token?
I believe you should just have the following endpoint REST /user/step which returns the step number for a current user (defined by the session token in the http only cookie) or it returns 401 code (Unauthorised) if the user is not logged in..
We have a JSP page and a Servlet page, where we pass the parameters via URL from JSP to Servlet. Below is the JSP link
Allergies
In our servlet, we do some process like below.
int id = Integer.parseInt(request.getParameter("idClient"));
//Do the work
RequestDispatcher d = request.getRequestDispatcher("view.jsp");
d.forward(request,response);
Unfortunately this makes the idClient 100% visible and it is also editable. We have noticed that the user can simply edit the idClient from the URL and access other client information too! Not only that, any one can access anyones info, whether the client is belong to them or not!
How can we stop this?
Get the logged-in user.
Check whether that user is supposed to be able to access this client's details.
If not, return an error page instead of the client details page.
I can't be more specific without knowing the details of your existing code and database structure.
In annotation based spring controller. if a user was on url.com/first/page and clicked a link or submitted a form pointing to say url.com/second/page .
How to make the second/page know the url of /first/page so that the second/page can
1) redirect the user to the first/page again when the form values are processed.
2) or show a back button link to the /first/page?
Edit 1 --
request.getHeader('Referer') is another but those I think are browser based on the mercy of browser. If the browser dont do it, we cant know. I wanted a way which is application wide. some how passing the url from one page to another
Edit 1 end --
you can use two below methods:
request.getAttribute("javax.servlet.forward.request_uri")
or
request.getHeader("Referer");
In above methods you are trusting the browser behavior and also the container which make the request object available to you. I don't know why you don't want to use this method.
Or
you can get the current page/serlvet url save it in the session and use it in the second page.
String requestUrl=request.getRequestURL();
session.setAttribute("pervious_page",requestUrl);
Then in the second page:
session.getAttribute("pervious_page");
I have a strange re-occurring problem with requests being made to j_spring_security_check via GET method.
All my login forms use POST to j_spring_security check for posting login credentials. Yet, application users reported on several occasions that sometimes they get an error page when trying to log in. I tracked those situations in the logs and it looks like people visit the login page and then next request is GET to j_spring_security_check.
It happend to me once too, but I cannot reproduce it.
Do you have any ideas why this may happen? Could spring security redirect to j_spring_security for some reason?
I double checked html and javascript there are no mentions of j_spring_security_check except in the action field of form elements which all have method set as POST.
Any help or ideas would be appreciated.
EDIT: additional information:
WebApp is served by Tomcat. There is Apache reverse proxy in front of it. Pages that contain login forms pass w3c validations.
After almost a month, we have finally figured out why this thing happens in google Chrome.
Apparently, if you submit a form using SHIFT+ENTER Chrome will open a new window and make a GET request instead of a POST request. Since some users have uppercase characters / special characters as a last letter of the password they type in the last letter with shift pressed and the press enter to log in while not yet releasing shift key. And the result is GET request to j_spring_security check. We will fix this by intercepting shift + enter in javascript.
I'm having a problem in identifying a session timeout page and a page navigated directly...
user will first fill a form and submits it, based on the search he will land on information page. for some reason if he try to type the url of information page instead of coming through search page how can i restrict him?
i tried using an indicator varaible in session, but that is getting in conflict with session timeout.... how do i differentiate if it is session timeout or direct navigation?
could someone please shed some light on this and point me in right direction?
From my understanding your question is:
User should not be able to access a certain page say Page1.xhtml directly. He should first fill in a form on page2.xhtml and then should be directed to this page by the server itself.
Solution:
You could put the page1.xhtml inside web-inf directory of your webapp, which will restrict direct access to your webpage.
You could you use securityConstraint tag of the web.xml and make use of container security to restrict direct access.
You could test for a server side session timeout as follows:
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
// The session has been timed out (or a hacker supplied a fake cookie).
}
The request is here the HttpServletRequest which you can obtain in the JSF context from the ExternalContext#getRequest() or, actually better, inside a Filter by just downcasting the ServletRequest argument.
As a completely different alternative, you could also introduce a timed ajax poll as a "heartbeat" so that the session never expires as long as the user has the page open in the browser.