I have this Spring+Thymeleaf project, where user must answer to question and after that he/she can fill out a form.
I want to limit access to this form page (/finish.html), so that you cannot access it directly by typing it to browser and you must have answered correctly to a question.
I have this piece of code,
Long max = difficultyLevels.stream().map(d -> d.getLevel()).max(Long::compareTo).get();
if (levelId > max) {
return "redirect:/finish";
}
where I think I should add something to grant access to /finish.html -page. But how I do it?
A redirect causes a new client request. So if you want to protect the /finish endpoint securely there are a few strategies:
You can place a value on the session that you can check in the /finish controller before you render the page.
You could also use redirect attributes to pass some sort of encrypted token and check that in the finish controller. See What are ways for pass parameters from controller after redirect in spring mvc?.
You could also use a forward instead of a redirect. You can add data to the servlet request as described here: Spring forward with added parameters?. This may not work for you as it won't change the browser url.
Related
When I tried to find the solution for the challenge I'm facing at the moment, I was provided with many approaches which didn't seem to quite fit my problem.
Here's what I'm facing:
I have a back-end integrated with Spring Security and the front-end is all built using AngularJS. We have 2 sets of users - legacy and new. The new feature requires when a legacy user signs in, redirect the user to the password reset page and have the legacy user reset his password to meet the new password standards.
This is the approach I have taken to deal with this:
Create a filter that intercepts every user request, checks if the user is a legacy user or not. If he is, redirect the user to the password reset page.
The challenge I'm facing at the moment is to let AngularJS know from the filter that it should redirect the user to the password reset page.
When I call sendRedirect on the HttpServletResponse, it's not redirecting to the destination page. I know I'm missing something here. Can someone help me with the approach here?
Thanks.
Like Dvorog said in his comment, you have to send a redirect response to your client, such as 302. You should specify the redirect location in the header.
Then, in client side, you can manage the header in the error callback
$http.get('/someUrl').success(function(data, status, headers, config) {
})
.error(function(data, status, headers, config) {
// check status and get headers informations(ie location) here to make redirection
});
You will find more detail in the documentation
Since you asked for a better solution (in the comments) this is what I would do:
Create a guard that will be assigned on all of the routes that require the user to be authenticated in order to access them. This guard should check the role of the authenticated user, and if the user is a legacy one, then redirect the user to the "change password" site. This way, you won't have to implement special logic on the backend and send redirect requests.
Someone knows how to open a popup login to authenticate (using spring security) when the user does something that needs to be authenticated and he is not.
For example: Lets imagine the page has one button "buy now" that add the product to the cart and perform the checkout (buy now page), if the user is already authenticated, or, opens a popup for the user perform the authentication.
If the authentication is successful than the spring redirects to the "buy now" page or stays in that page with the popup opened (with an error message "wrong login").
I already searched in google for a kind of solution but without luck.
Someone can point me in the right direction?
Thanks
Just an idea, haven't had time to test it. It's client-side only.
Put an Eventlistener on the Link/Button-Click-Event
Use Javascript and call the form-action or link via XMLHttpRequest
Check the HTTP status code: xhr.status
if (OK) replace the current url with the target url (via Html5 History API) and replace the entire document with xhr.responseText (What other options for replacing entire HTML document via W3C DOM)
else if (Redirect) just follow the redirect
else if (Unauthorized) open popup
Break down the task into components.
Create a light box that activates based on your critera.
Make your form submittable via ajax.
Your authentication controller needs to do the following:
if succesfull -> redirect to checkout page
if un-succesfull return a fragment advising why its incorrect.
If return of incorrect you need to refresh your form element completely to ensure no csrf attacks.
Thats way i've done mine, can't give you code as it varies depending on how you have setup your project and view rendering.
You can maybe use http basic authentication, it at least will always open a popup when you need to be authenticated. http://www.baeldung.com/spring-security-basic-authentication
You can use ajax call when user hits on Buynow button to check whether the user is authenticated or not.
If the user is authenticated submit or forward the product cart form to next view (controller method).
If not authenticated you can open a popup for login.
In login form use ajax to validate user if success submit cart form to next view else give error message.
Store the cart information in the session so that you can use them in the next view.
Pop box implementation on some event has to be done you (you can use any frontend framework for this). Whereas authentication is concern, "project-security.xml" will do it for you. You should only configure it as per your requirement.
Actually Spring Security supports the redirect out of the box, take a look at SavedRequestAwareAuthenticationSuccessHandler, so the only thing you have to do is to secure the url(for e.g. you have something like <intercept-url pattern = "/purchase/*" access = "isAuthenticated()" /> (or if access = "hasRole('user') whatever you do there) of your purchase button(which does request like "/purchase/"productIdHere" or /purchase?productId=someProductId), which will then redirect user to login page and after successful login he should be back to his original page.
And in your controller you can handle the request like:
#Controller
...
#RequestMapping(value = "/purchase..., method = ....)
public ModelAndView purchase(#PathVariable("productId") String/Long productId (or #RequestParam etc...)
Product someProduct = someService.getByProductId(productId);
ModelAndView mav = new ModelAndView("view.name");
mav.setObject("product",product);
return mav;
You have to match other things per your needs, just trying to point the right direction as you asked.
Hope it helps.
You can use a CSS HTML login form (just search the web for it) with Ajax authentication or use the Spring Http Basic Auth popup. Every page should check if the user is authenticated or not (showing the popup).
Check these two articles showing how you can implement both solutions:
Adding Http Basic Auth to RESTful Services in Java and Spring
Spring security Ajax login
Spring security works over Spring MVC - it uses redirects. So the idea is when a user tries to reach a "secured" content, and he has not been authenticated, then HTTP 302 is return and redirect to the login page. If you are interested in pop-up window, you break the MVC model, and it can be implemented of course, but your life will be much harder ....
I have the following problem. I want to use a controller, same for every page in my application. It is a common form included via include jsp in every page and it sends a mail to a predefined email account. The problem is, when I am posting the form, I get redirected to a blank page, with the url being my RequestMapping value despite the method called is actually void. So I need now to redirect me, after sending the mail to the page where I came from. How do I get access to the url link of the page that redirected me, into sending the email? Thanks
When returning void and one isn't handling writing the response yourself Spring MVC delegates detection of which view to render to a RequestToViewNameTranslator for which there is a single implementation the DefaultRequestToViewNameTranslator. Which basically takes the incoming URL, strips any suffixes (like .html etc.) and uses that as the viewname. The behavior you see now.
I guess you have 3 possible solutions
Add a hidden form attribute which contains the current page
Use the referer request header to determine where the request came from (not a 100% solution, See Alternative to "Referer" Header)
Submit the form through ajax so that you stay on the current page
For option 2 add the HttpServletRequest as a parameter to your request handling method and retrieve the header.
public String foo(HttpServletRequest request) {
String referer = request.getHeader("Referer");
return "redirect:" + referer;
}
I would probably go for option 3 and maybe add option 1 as a fallback when no javascript is available.
This question already has answers here:
How to use java.net.URLConnection to fire and handle HTTP requests
(12 answers)
Closed 7 years ago.
If I use a browser to send information to the server (for example using a log-in, password page), I just fill the user text-box and the password text-box and clicking on the log-in button.
I would like to send this information but without having to use the browser. I would like to 'fill' the text-boxes but without having to do it manually in the browser. May be using a Servlet.
My question is: How to send information in text-boxes, for example, to a website, doing it from a Servlet?
why not just make a call to the URL from Java using a URL like http://your.domain.name/your/servlet/path?userFieldName=THE_VALUE_YOU_WANT_TO_PASS&passwdFieldName=PASSWORD
The servlet will feel like the values are coming from those boxes.
Or you may want to dive into Apache HTTP Client to mimick a request sent from an client.
uh..oh.. are you doing functional testing? Why not look into JMeter?
Updates as per comment
You need to know what actually form submission does? It basically forms a query string composed of Key-Values (KV) pair.
So, if you have a a text field named tfield where user has typed some text, and there is a drop down named, ddfield where user has selected optionX which has value optionX-Val. And this form gets submitted to a URL, http://my.domain.name/my/servlet -- the browser will send a request which will look like
http://my.domain.name/my/servlet?tfield=some%20text&ddfield=optionX-Val
If you want to mimic form submission, you will have to manually create a URL that has a request string containing all the fields and their values as FIELD_NAME=FIELDVALUE ordered pair separated by ampersand (&)
ah, great idea. If you use Firebug (a Firefox extension), open the NET panel in Firebug, make a manual submission of the form that you wanted to mimic. See what request is posted when you submitted the form. It will have exact URL format that you are after. Copy this URL, replace the values and make fake submissions as much as you want.
Hope this helps.
It is not clear to me what you really up to. I assume that the servlet will be the one who will send the data. Here some examples.
Using setAttribute then Forward the request
//On your servlet
request.setAttibute('user', 'admin');
request.setAttribute('password', '123');
getServletContext().getRequestDispatcher("page.jsp").forward(request, response);
//On your jsp page get the value using EL
<span>${user}</span>
Using session
//On your servlet
HttpSession session = request.getSession(true);
session.setAttribute('user', 'admin');
session.setAttribute('password', '123');
getServletContext().getRequestDispatcher("page.jsp").forward(request, response);
//On your jsp page get the value using EL
<span>${user}</span>
The above example is intended to work within the web application. To send information to another web application, which expecting a request. See sample below.
//On your jsp or servlet, you can also do the same within web application
request.sendRedirect('http://example.com?user=admin&password=123');
//on your jsp #example.com
<span>${param.user}</span>
If this is not what you mean, adding more details will be a help.
a servlet takes care of the other end: it's basically a handler for http requests that lives inside a servlet container. If I understand you correctly, you're wanting to send an http request. You can do that using command-line tools like curl, or if you want to stay within java land, you could try this example on exampledepot. Use your favourite search engine to search for more examples, e.g. with search terms such as "sending GET requests through a url".
In your situation, where you need to send information for username and password, you would need to look at the html and find the url for the form element's action attribute. Then you need to find the names of the username and password fields. Using these names as url parameters, you can construct a GET request that mimics sending a form.
NOTE: usually storing a password in plain text in code and/or sending it in plain text to a website is not a good thing to do.
Just in case anyone is interested, there is a plugin for Firefox called Tamper data. With it you can stop the sending of and http request and modify it. It will show you the "url" you need for sending the params, the values they currently have, and their name. You can check it out here. After that you can use a request.sendRedirect('url you got from Tamper Data');
i want to know how to generate a url in a servlet. I have a login servlet, and every time that add a user i want to gen. a url for each user profile.
Can anyone help me please?
The easiest way is to declare a servlet mapping like the following:
<servlet-mapping>
<servlet-name>UsersSelvlet</servlet-name>
<url-pattern>/Users/*</url-pattern>
</servlet-mapping>
Now, whenever you get a request for MyApp/Users/UserId you read the request path, get the userId and check if the user exists. If not you return 'Not found'. Otherwise you return the user's page.
This is a quick and dirty implementation of a RESTful service.
I think the solution of kgiannakakis is very good. I just want to add some details, because reading the comment of Agusti-N I have the suspect that may be he is missing something.
Let's say that you have the UsersServlet described by kgiannakakis, a jsp called showUserProfile.jsp and an userBean that has all the properties of the user's profile needed to be shown in the jsp.
When a new user registers to your application, you need to do nothing more than you already do now. Just register a new user in the db, and forget the login servlet.
Now suppose that I registered to your app with my username alexmeia.
When someone digit the url yourApp/Users/alexmeia the UsersServlet is called. This servlet gets the username alexmeia from the request url, checks in the DB if
this username exists and if exist load all the properties of this user in the userBean.
After that, forward to showUserProfile.jsp, which shows the user profile reading it from the userBean.
Obviously, if the user alexmeia is not in the Db, you can redirect to a generic userNotFound.jsp, or go to home page and show a message and so on...
This works for all the registered users in the same way. You don't need to really create a real new url for every new user.
It sounds like you might want to look into REST technologies. There is a tutorial here you might want to have a look at.
Do you need URL rewriting? Something like this, perhaps, but instead of RMI generate your own user id