here I have a change password page. And I will log the user out once the password has been changed successfully but I have to inform user that the password has been changed successfully before I log him/her out. How should I do the trick? Below is my code:
#RequestMapping(value = "/changepassword", method = RequestMethod.POST)
public String change(Model model, String oldPassword, String newPassword, Principal principal) throws NoSuchAlgorithmException {
//Some method
return "redirect:/somename/j_spring_security_logout";
}
}
I guess it is a simple trick but I just can't figure it out..
I see 2 options:
1.Just make an ajax call to change the password. And then redirect on client side instead of server side. For example (mnemo code in javascript)
ajaxCall.success = {
showMessage("Your session will be terminated. Please login again.")
//wait for 3 seconds and then redirect
setTimeout(function(){ window.location = "/somename/j_spring_security_logout" }, 3000);
}
2.Keep the code as is, just add a request parameter on redirect:
return "redirect:/somename/j_spring_security_logout?notify_about_password=true";
On your logout page add some extra-logic to handle this request parameter.
Related
I have a controller with #ResponseBody annotation. What I want to do is if this user doesn't exists process user's Id and return a json object. If exists redirect to user page with userInfo. Below code gives ajax error. Is there any way to redirect to user page with userInfo?
#RequestMapping(value = "/user/userInfo", method = {RequestMethod.GET})
#ResponseBody
public String getUserInfo(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) {
if(...){
.....//ajax return
}else{
modelMap.addAttribute("userInfo", userInfoFromDB);
return "user/user.jsp";
}
}
Well, this method is annotated with #ResponseBody. That means that the String return value will be the body of the response. So here you are just returning "user/user.jsp" to caller.
As you have full access to the response, you can always explicitely do a redirect with response.sendRedirect(...);. It is even possible to explicitely ask Spring to pass userInfoFromDB as a RedirectAttribute through the flash. You can see more details on that in this other answer from me (this latter is for an interceptor, but can be used the same from a controller). You would have to return null to tell spring that the controller code have fully processed the response. Here it will be:
...
}else{
Map<String, Object> flash = RequestContextUtils.getOutputFlashMap(request);
flash.put("userInfo", userInfoFromDB);
response.redirect(request.getContextPath() + "/user/user.jsp");
return null;
}
...
The problem is that the client side expects a string response that will not arrive and must be prepared to that. If it is not, you will get an error client side. The alternative would then be not to redirect but pass a special string containing the next URL:
...
}else{
Map<String, Object> flash = RequestContextUtils.getOutputFlashMap(request);
flash.put("userInfo", userInfoFromDB); // prepare the redirect attribute
return "SPECIAL_STRING_FOR_REDIRECT:" + request.getContextPath() + "/user/user.jsp");
}
and let the javascript client code to process that response and ask for the next page.
Here is my spring login handler
public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
HttpSession session = request.getSession();
LoggedInUser logginUserObj = (LoggedInUser)authentication.getPrincipal();
String userId = logginUserObj.getUserId();
session.setAttribute("userId", userId);
session.setAttribute("userName", logginUserObj.getName());
session.setAttribute("hasPhoto", user.getProperty(UserVertex.profilePhotoUploaded.toString()));
if(logginUserObj.getActivateLink()!=null)
session.setAttribute("activateLink", logginUserObj.getActivateLink());
try {
Object referUrl = session.getAttribute("Referer_url");
if(referUrl != null){
session.removeAttribute("Referer_url");
response.sendRedirect(referUrl.toString());
}
else
response.sendRedirect("profile/"+userId);
} catch (IOException ex) {
logger.error(ex);
}
}
}
My client is in plain html, jQuery (in cordova). So my question is if everytime user makes a request, how will I know that requested user is logged in or not ?
e.g. here is a sample :
$.ajax({
url: "addNewpost",
data:{}
})
Here only a loggedin user can add new post. So when i am calling addNewpost rest service in spring #RestController how will i know that request is from logged in user ?
Since you're using a success handler so before the request goes to success handler it goes to authentication manager.In authentication manager if you have configured any authentication provider there authenticity of the user will be check and if it returns success then the call will go to onAuthenticationSuccess.In the authentication provider you actually look for some values in the request header depending upon the type of authentication provider you are using.If its missing then the user is not logged in.Here is a better picture with one example(Here its also checking authorization for admin)
You can also refer to this link
Hope this gives you a clear picture!!
First you have to make sure that your web app returns 401 unauthorized when you are not logged in
Then with JQuery you use the error callback more or less as in following snippet, usually checking that jqXHR.status is 401 (unauthorized)
$.ajax({url:url, data:{}, error: function(jqXHR, e, x){
alert("Error #" + jqXHR.status + "\n\n\t" + x );
});
Whether the request is from a logged in user, in the server, depends on your security configuration, you should not check in the controller "manually" but just be sure that configuration declarations are correct.
BTW not sure if is the case to redirect to ANY url after login
In Spring I usually did a redirect-after-submit(get method mapping) to prevent the user of submitting a form ,
but when i pressing F5 it will go to get method mapping again and display me this kind of confirm message. how could i prevent this message every time on F5.
Here is the code for controller -
ScheduleDetail objScheduleDetail = new ScheduleDetail();
HttpSession session = request.getSession(true);
String condition = "";
try{
int careProfessionalIDF = (Integer) session.getAttribute("careProfessionalIDF");
condition = "CareProfessionalIDF = "+careProfessionalIDF;
objScheduleDetail.setCareProfessionalIDF(careProfessionalIDF);
}catch (Exception e) {
int careProviderIDF = (Integer) session.getAttribute("careProviderIDF");
condition = "CareProviderIDF = "+careProviderIDF;
objScheduleDetail.setCareProviderIDF(careProviderIDF);
}
List<ScheduleDetail> ScheduleDetailList = objScheduleDetailManager.getAllScheduleDetail(condition+" ORDER BY ScheduleDetailIDP DESC");
model.addObject("List_of_ScheduleDetail",ScheduleDetailList);
model.addAttribute("ScheduleDetail", objScheduleDetail);
return "hospital/scheduleDetail";//jsp page
edited code
#RequestMapping("/editAddressType.html")
public String editAddressType(ModelMap model,HttpServletRequest request)
{
int addressTypeIDP = Integer.parseInt(request.getParameter("AddressTypeIDP"));
AddressType objAddressType = new AddressType();
objAddressType = objAddressTypeManager.getByID(addressTypeIDP);
model.addAttribute("AddressType", objAddressType);
return "jsp/addressType";
it open addressType.jsp with data tht we bind with `model.addAttribute`. now if i press F5 it show alert message as above image.
**get method**
#RequestMapping(value="/getAddressType.html", method=RequestMethod.GET)
public String getAddressType(ModelMap model, HttpServletRequest request) throws RemoteException
{
AddressType objAddressType = new AddressType();
model.addAttribute("AddressType", objAddressType);
return "hospital/addressType";
}
If you implement the POST - REDIRECT - GET pattern correctly, you will not see the warning from the browser that you mentioned. The warning is shown when the Page being viewed is in response to a POST request. The traditional pattern, FORM - POST - SUCCESS page.
The code you provided in the question is not enough to reach the root cause of the problem. I'm listing key points of the implementation here, please compare with your code and you'll understand what the mistake is.
To show the user the form, where they are supposed to enter data for submission. (Just the starting point, could be any page in your application.)
#RequestMapping(value = "/checkout/{cartId}.htm", method = RequestMethod.GET)
public ModelAndView showCheckoutForm(...) {
......
return new ModelAndView("/WEB-INF/jsp/form.jsp")
}
The form POSTs to a handler method, which issues a redirect to the user, pointing to a URL that will show the details of the resource created as a result of the POST.
#RequestMapping(value = "/checkout/{cartId}.htm", method = RequestMethod.POST)
public View submitCheckoutForm(....) {
return new RedirectView("/checkout/confirmation/" + cartId + ".htm");
}
The details of the created resource will be shown by a handler method like the following. Note that at this point, if your implementation worked properly, the URL in the user's browser will change to the path redirected by the POST handler. And a fresh GET request will be issued to the server.
#RequestMapping(value = "/checkout/confirmation/{cartId}.htm", method = RequestMethod.GET)
public ModelAndView showCheckoutConfirmation(....) {
return new ModelAndView("viewThatShowsCheckoutConfirmation");
}
If your implementation is similar, the confirmation page is a result of a GET request, so browsers won't issue a warning for re-POSTing data if you refresh the page.
My suspicion is that your POST handler is not issuing a redirect to the user, it is instead rendering the confirmation page itself.
Hope this helps. Please let me know if this does not solve your problem.
can you please tell me how to redirect to next page after successfully login in GWT?
I have created the service interface and its implementions but dont know how to redirect the page after login authentication.
Share your views guyz.
and also tell me how to get sessiontimeout and then redirect automatically to login page in gwt.
Thanx
You can use Window.Location.replace(String newURL) to switch pages.
As for the session timeout, that depens on what kind of session management you are using.
The easiest would be to include the information "session expired" in every RPC call you make, for example with a custom exception:
Server
public String myRpcCall() throws SessionExpiredException {
if(!SessionManager.isSessionValid()) { // depends on your session management
throw new SessionExpiredException;
}
return some_stuff(); // whatever you want to do
}
Client
public doCall() {
AsyncCallback<String> cb = new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
if(caught instanceof SessionExpiredException) {
// inform the user and redirect to login page
Window.Location.replace("login.html");
}
// handle other errors
}
// TODO onSuccess(String)
};
service.myRpcCall(cb); // your rpc call goes here
}
I have a mailing campaign where all links include google analytics tracking code such as:
http://example.com/account/somePage.html?utm_source=example&utm_medium=email&utm_campaign=reminder
The context /account/** is protected via Spring security and once the user clicks on the link on the email, he is re-directed to login BEFORE actually seeing somePage.html. This way the first page that is displayed is something like /login.do which does not have the analytics tracking code. Therefore google does not track my source, medium and campaign parameters.
Any ideas how to solve?
Based on http://support.google.com/analytics/answer/1009614?hl=en , I updated my LoginController that shows the login page to redirect to /login?GOOGLE_PARAMATERS:
private static final String ALREADY_REDIRECTED = "ALREADY_REDIRECTED";
....
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView loginView(HttpServletRequest request, HttpServletResponse response){
....
Boolean alreadyRedirected = (Boolean) request.getSession().getAttribute(ALREADY_REDIRECTED);
if (alreadyRedirected==null){
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response);
if (savedRequest!=null){
String source[] = savedRequest.getParameterValues("utm_source");
if (source!=null && source.length>0){
// we need to redirect with login instead
String mediums[] = savedRequest.getParameterValues("utm_medium");
String medium = mediums.length==0 ? "" : mediums[0];
String campaigns[] = savedRequest.getParameterValues("utm_campaign");
String campaign = campaigns.length==0 ? "" : campaigns[0];
String redirect = "redirect:/login?utm_source=" + source[0] + "&utm_medium=" + medium + "&utm_campaign=" + campaign;
mav.setViewName(redirect);
// mark not to do twice
request.getSession().setAttribute(ALREADY_REDIRECTED, new Boolean(true));
return mav;
}
}
}
We have similar problem and have solved with the next solution.
We have a signup form via Ajax, and in the callback if everything is OK we auto-login the user and lost Google Analytics tracking code for Funnel visualization because of Spring Security session invalidation and set up a new cookie.
What we have done by JS just before auto-login call the new user this
_gaq.push(['_trackPageview', '/signupDone']);
https://gist.github.com/moskinson/5418938
signupDone is a fake url that does not exists.
This way GA receive a call of a new url is loaded and we can track the funnel!
http://packageprogrammer.wordpress.com/2013/04/19/seguimiento-con-google-analytics-a-traves-del-login-con-spring-security/