spring - Handling MaxUploadSizeExceededException in servlet filter, how to set flash message in redirect? -
when implementing spring security , csrf protection, new problems arose multipart file uploading. reading several threads issue, encountered following solutions subsequent problems:
first, cause of problems uploading file did not work anymore after enabling csrf (actually is enabled default in spring security). because when using multipart request csrf token not send, multipartfilter must specfied before spring security filter. according documentation of spring security (http://docs.spring.io/spring-security/site/docs/4.0.4.release/reference/htmlsingle/#csrf-multipartfilter) can done implementing beforespringsecurityfilterchain method in securitywebapplicationinitializer class:
public class securitywebapplicationinitializer extends abstractsecuritywebapplicationinitializer { @override protected void beforespringsecurityfilterchain(servletcontext servletcontext) { // todo auto-generated method stub insertfilters(servletcontext, new multipartfilter()); } }
this did not work instead threw exception, , after research appeared configured multipartfilter servletfilter resolves multipart requests looking multipartresolver in root application context using default name of "filtermultipartresolver".
so following declaration had modified , moved mvcconfig appconfig class:
// moved mvcconfig in fix multipart exception //the bean must has id of filtermultipartresolver picked //multipartfilter configured in beforespringsecurityfilterchain //(see securitywebapplicationinitializer) @bean(name="filtermultipartresolver") public commonsmultipartresolver multipartresolver() { commonsmultipartresolver multipartresolver = new commonsmultipartresolver(); multipartresolver.setmaxuploadsize(2000000); multipartresolver.setmaxinmemorysize(500000); return multipartresolver; }
now file uploading did work again expected little later found out maxuploadsizeexceededexception thrown when file big not handled anymore @exceptionhandler method in exceptionhandlingcontrolleradvice class, instead returned in ugly http 500 status page tomcat.
reason because of multipartfilter, exception thrown before request has reached dispatcherservlet controlleradvice never called.
and continue cascade of problems , workarounds, after reading various post issue implemented dedicated filter catch , handle exception , put in filter chain:
public class multipartexceptionhandler extends onceperrequestfilter { private static logger logger = loggerfactory.getlogger(multipartexceptionhandler.class); @override protected void dofilterinternal(httpservletrequest req, httpservletresponse res, filterchain filterchain) throws servletexception, ioexception { try { filterchain.dofilter(req, res); } catch(maxuploadsizeexceededexception me) { handle(req, res, me); } catch(servletexception se) { if (se.getrootcause() instanceof maxuploadsizeexceededexception) { handle(req, res, (maxuploadsizeexceededexception) se.getrootcause()); } else { throw se; } } } private void handle(httpservletrequest req, httpservletresponse res, maxuploadsizeexceededexception me) throws servletexception, ioexception { // todo auto-generated method stub logger.info("maxuploadsizeexceededexception handled in custom filter"); string redirect = urlutils.buildfullrequesturl(req); req.getsession().setattribute(keyconstants.flash_error_key, "file big!"); res.sendredirect(redirect); } }
and multipartexceptionhandler filter added filter chain adding insertfilters method:
@override protected void beforespringsecurityfilterchain(servletcontext servletcontext) { // todo auto-generated method stub insertfilters(servletcontext, new multipartexceptionhandler(), new multipartfilter()); }
and maxuploadsizeexceededexception indeed caught filter , redirected page shown. problem, however, response.sendredirect method not have functionality set error flash message. in original @exceptionhandler method, donw in following way:
redirectview rv = new redirectview(redirecturl); flashmap outputflashmap = requestcontextutils.getoutputflashmap(req); if (outputflashmap != null) { outputflashmap.put(keyconstants.flash_error_key, "file large"); } return rv;
but in new exception handler filter, not work. call requestcontextutils.getoutputflashmap(req) returns null.
therefore set flash message manually in session before doing redirect , displayed, remains in session has removed explicitly somewhere after finishing redirect. seems bad practice me have not found better solution yet. after pretty time consuming cascade of issues after starting using springsecurity csrf protection hope there better solution setting flash message.
the problem of not showing flash message due use of:
flashmap outputflashmap = requestcontextutils.getoutputflashmap(req);
according documentation, requestcontextutilsutility class "for easy access request-specific state has been set dispatcherservlet." , because handling en exception before reaching dispatcherservlet, getoutputflashmap method returns null.
when using following code, flash message generated!
flashmapmanager flashmapmanager = new sessionflashmapmanager(); flashmap fm = new flashmap(); fm.put(keyconstants.flash_error_key, "file large"); flashmapmanager.saveoutputflashmap(fm, req, res);
Comments
Post a Comment