java - CSRF protection prevents me from uploading a file -
i created simple app spring boot , spring security contains :
- a login form
- an "upload" form (with associated controller on backend's side)
problem : spring security has built-in default csrf protection. works common rest calls prevents me uploading file : error message :
invalid csrf token 'null' found on request parameter '_csrf' or header 'x-xsrf-token'.
if deactivate csrf protection, can upload file.
i created sscce illustrate problem. steps reproduce :
- launch application (main class
com.denodev.application
) - connect
localhost:8080
- authenticate credentials :
- login :
user
- password :
password
- login :
- when redirected "upload" form, try upload file.
- in class
application
, feel free activate/deactivate csrf protection, restart app , retry.
the relevant part of code :
@restcontroller @springbootapplication public class application { public static void main(string[] args) { springapplication.run(application.class); } @requestmapping(value = "/upload-file", method = requestmethod.post) @responsebody public string uploadfile(@requestparam("file") multipartfile file) { return "successfully received file "+file.getoriginalfilename(); } @configuration @order(securityproperties.access_override_order) protected static class securityconfiguration extends websecurityconfigureradapter { @override public void configure(httpsecurity http) throws exception { http .authorizerequests() .antmatchers("/", "/**/*.html", "login").permitall() .anyrequest().authenticated() .and() .formlogin() .successhandler(successhandler()) .failurehandler(failurehandler()) .and() .exceptionhandling() .accessdeniedhandler(accessdeniedhandler()) .authenticationentrypoint(authenticationentrypoint()) .and() //1 : uncomment activate csrf protection .csrf() .csrftokenrepository(csrftokenrepository()) .and() .addfilterafter(csrfheaderfilter(), csrffilter.class) //2 : uncomment disable csrf protection //.csrf().disable() ; } /** * return http 200 on authentication success instead of redirecting page. */ private authenticationsuccesshandler successhandler() { return new authenticationsuccesshandler() { @override public void onauthenticationsuccess(httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, authentication authentication) throws ioexception, servletexception { httpservletresponse.setstatus(httpservletresponse.sc_ok); } }; } /** * return http 401 on authentication failure instead of redirecting page. */ private authenticationfailurehandler failurehandler() { return new authenticationfailurehandler() { @override public void onauthenticationfailure(httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, authenticationexception e) throws ioexception, servletexception { httpservletresponse.setstatus(httpservletresponse.sc_unauthorized); httpservletresponse.getwriter().write(e.getmessage()); } }; } /** * return http 403 on "access denied" instead of redirecting page. */ private accessdeniedhandler accessdeniedhandler() { return new accessdeniedhandler() { @override public void handle(httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, accessdeniedexception e) throws ioexception, servletexception { httpservletresponse.setstatus(httpservletresponse.sc_forbidden); httpservletresponse.getwriter().write(e.getmessage()); } }; } private authenticationentrypoint authenticationentrypoint() { return new authenticationentrypoint() { @override public void commence(httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, authenticationexception e) throws ioexception, servletexception { httpservletresponse.setstatus(httpservletresponse.sc_unauthorized); httpservletresponse.getwriter().write(e.getmessage()); } }; }
what tried :
the spring security's documentation multipart advices place multipartfilter
before spring security. explains how plain old webapp editing web.xml
file. not applicable spring boot , cannot figure equivalent syntax.
i tried expose multipartfilter
annotations @bean
, order
several options still struggle it.
any ideas?
this works me :
add directive upload file in client side :
app.directive('filemodel', function ($parse) { return { restrict: 'a', link: function(scope, element, attrs) { var model = $parse(attrs.filemodel); var modelsetter = model.assign; element.bind('change', function(){ scope.$apply(function(){ modelsetter(scope, element[0].files[0]); }); }); } }; })
upload file :
<input type="file" file-model="filetoupload"/>
this how upload file server :
var formdata = new formdata(); formdata.append("file", filetoupload); $http({ method: 'post', url: 'the url', headers: {'content-type': undefined}, data: formdata, transformrequest: angular.identity }) .success(function(data, status){ })
Comments
Post a Comment