how to prevent confirm alert In Spring MVC on F5 - spring

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.

Related

How to redirect from spring ajax controller?

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.

Spring security alert user before logout

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.

spring social facebook accessToken with 400 error

Hi please help am new to spring social,i am getting the 400 error while getting the access token from the AUTHORIZATION_CODE..
my code is as follows
#RequestMapping(value = "/facebook", method = RequestMethod.POST, produces = "application/json")
#ResponseBody
public Object getFacebookLoginPage(#RequestBody SocialCommand socialCommand) throws Exception {
loggerService.debug("In ShareController", "getFacebookLoginPage method for facebook", "returns the JSON response for the input socialCommand");
Result result = new Result();
result.status = "OK";
dataObject = socialCommand;
FacebookConnectionFactory connectionFactory = new FacebookConnectionFactory(msgprop.getProperty("facebook.appId"), msgprop.getProperty("facebook.appSecrete"), msgprop.getProperty("facebook.namespace"));
oAuth2Operations = connectionFactory.getOAuthOperations();
OAuth2Parameters params = new OAuth2Parameters();
params.setScope(msgprop.getProperty("facebook.scope"));
params.setRedirectUri(msgprop.getProperty("facebook.redirectURI"));
// params.set("Content-Type", MediaType.MULTIPART_FORM_DATA.getType());
String authorizeUrl = oAuth2Operations.buildAuthorizeUrl(GrantType.AUTHORIZATION_CODE, params);
System.out.println(authorizeUrl);
SuccessResponse successResponse = new SuccessResponse();
successResponse.resultObj = authorizeUrl;
result.response = successResponse;
return result;
}
and the callback controller is as follows
#RequestMapping(value = "/facebook/callback", params = "code", method = RequestMethod.GET)
public Object faceBookCallback(#RequestParam(value = "code") String callBackCode, Model model) throws IOException {
loggerService.debug("In ShareController", "faceBookCallback method for facebook", "returns the JSON response for the input socialCommand");
MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
formData.add("client_id", msgprop.getProperty("facebook.appId"));
formData.add("client_secret", msgprop.getProperty("facebook.appSecrete"));
formData.add("scope", msgprop.getProperty("facebook.scope"));
formData.add("redirect_uri", msgprop.getProperty("facebook.redirectURI"));
formData.set("grant_type", "authorization_code");
formData.set("Content-Type", MediaType.MULTIPART_FORM_DATA.getType());
AccessGrant accessGrant = oAuth2Operations.exchangeForAccess(callBackCode, msgprop.getProperty("facebook.redirectURI"), formData);
System.out.println(accessGrant.getAccessToken());
appStatus.getActivityId();
SocialCommand socialCommand = (SocialCommand) dataObject;
socialCommand.setAppType("facebook");
socialCommand.setAccessToken(accessGrant.getAccessToken());
getImageLocation(socialCommand);
model.addAttribute("activityId", appStatus.getActivityId());
return "backToViewDetails";
}
oAuth2Operations.exchangeForAccess giving the 400 bad request
A couple of things I notice...
First, why are you writing your own controller for performing the OAuth dance instead of using ConnectController that Spring Social provides? ConnectController can handle all of the redirects for you and has been part of Spring Social from the beginning. Spring Social Showcase (https://github.com/spring-projects/spring-social-samples/tree/master/spring-social-showcase) is an example of a project that uses ConnectController.
Even so, assuming you have good reason for writing your own connection controller, I see nothing in getFacebookLoginPage() that performs the actual redirect to Facebook, so I can only assume that happens in code not shown. Then when the redirect comes back from Facebook, I'm puzzled as to why you set the content type and most of those parameters before calling exchangeForAccess(). (Even then, you're setting what looks like a request header, but you're setting it as a form parameter...not necessary, but also not what you had in mind.)
Again, I encourage you to take a look at ConnectController (https://github.com/spring-projects/spring-social/blob/master/spring-social-web/src/main/java/org/springframework/social/connect/web/ConnectController.java). It will probably do what you need it to do. And even if you still feel the need to writing your own controller, you can look at how ConnectController works as a guide to how to write your own controller.

Display message to user on expired session when using wicket-auth-roles

Hi I have been unable to solve the following problem in Wicket 6.*:
In our webapp we are using wicket-auth-roles to manage authentication/authorization. When session expires, user should be redirected to a page set by getApplicationSettings().setPageExpiredErrorPage(SomePage.class) on his next action. However, if the user tries to access a page which doesn't allow guests, he is redirected to a login page skipping the PageExpiredPage altogether.
My question is - how can I display "Session has expired." message to the user?
Among other things, I have tried session.info("message") during onInvalidate phase of session's lifecycle, however the feedback message is then rendered on the first page after login (not on the login page).
Thank you for your anwsers.
You could use a RequestCycleListener to record when a PageExpiredException is thrown.
public class ExceptionMapperListener extends AbstractRequestCycleListener {
#Override
public IRequestHandler onException(RequestCycle cycle, Exception ex) {
if (ex instanceof PageExpiredException) {
// Record in session or request cycle
// OR
// Create a RenderPageRequestHandler yourself and add a page parameter
// See DefaultExceptionMapper#internalMap(Exception)
}
return null;
}
}
// In Application#init():
getRequestCycleListeners().add(new ExceptionMapperListener());
ORINAL ANSWER
(kept because it could still help...)
I haven't tried it myself since I don't use wicket-auth-roles, but try overriding the method AuthenticatedWebApplication#restartResponseAtSignInPage() with something like this:
if (isSessionExpired()) {
PageParameters params = new PageParameters();
params.add("showSessionExpired", true);
throw new RestartResponseAtInterceptPageException(getSignInPageClass(), params);
} else {
throw new RestartResponseAtInterceptPageException(getSignInPageClass());
}
And then in the SignInPageClass, display the desired message if the showSessionExpired page parameter is present.
I'm not sure how you implement isSessionExpired(), but you seem to have that part already covered.
OR
Depending on how you implemented isSessionExpired(), maybe you could do the following in your SignInPageClass:
if (sessionExpired()) {
session.info("message")
}
After bernie put me on the right path, I eventually figured out a solution to the problem:
First it is required to override RequestCycleListener:
public class SessionExpiredListener extends AbstractRequestCycleListener {
public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler) {
if (handler instanceof IPageRequestHandler) {
IPageRequestHandler pageHandler = (IPageRequestHandler) handler;
HttpServletRequest request = (HttpServletRequest) cycle.getRequest().getContainerRequest();
//check whether the requested session has expired
boolean expired = request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid();
//check whether the requested page can be instantiated with the current session
boolean authorized = Session.get().getAuthorizationStrategy().isInstantiationAuthorized(pageHandler.getPageClass());
if (expired && !authorized) {
throw new PageExpiredException("Session has expired!");
}
}
super.onRequestHandlerResolved(cycle, handler);
}
}
Check for authorized prevents the session-expired message from displaying on log-out or when accessing unprotected pages.
Finally, you must register your listener and PageRequestHandlerTracker in your WebApplication:
getRequestCycleListeners().add(new SessionExpiredListener());
getRequestCycleListeners().add(new PageRequestHandlerTracker());

Losing Google Analytics tracking due to Spring Security login redirect

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/

Resources