Announcement Announcement Module
Collapse
No announcement yet.
Broke RESTfulness with Spring Security Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Broke RESTfulness with Spring Security

    Hi everyone,

    In my roo project I have an Entity that represents an uploaded File (name, mimetype, data itself). Now I have the upload working, I started to setup
    spring security.

    I have a whitelist configuration for URL-Interception allowing everyone for /static/** and /resource/** and /login but requiring login for everything else as the last rule.

    Now problem is this: In my controller, I adjusted code for the methods for creation (using POST) and update (using PUT). Unfortunately spring security seems to do a redirect so the original PUT-request from my update gets turned into a POST-request which in turn leads to the controller not finding a correct request mapping for the update URL (expects PUT, gets POST).

    Does that sound plausible?
    What can I do about it?

    (Sorry don't have access to code right now)

    Ben, I think this might be an easy one for you ;-)

  • #2
    It should work fine. But it does sound more like a Spring Security question than a Roo question, so you might find you receive better support by asking in the Spring Security forum. In any event would you please provide a debug-level log of the request processing and also the applicationContext-security.xml so we can help you figure it out.

    Comment


    • #3
      Thanks for the quick reply. You guys are really caring about your users
      Will provide logs, code and config as soon as I have access to it again.

      Besides: Do you know how ROO-8 is doing?

      Comment


      • #4
        ROO-8 is coming along brilliantly. Stefan is off to San Francisco this weekend to meet with our web team to fine-tune it some more. I've seen the work so far (it's not checked in yet) and it's impressive. I think people will really like it. We've spent a lot of time designing it so you can round-trip JSPX views in a very natural, usable way. And the JSPXs themselves are very small now and easily support the development of alternate tag libraries.

        Comment


        • #5
          Wonderful :-)
          Just lost one hours adjustments because I forgot to automaticallyMaintainView=false

          Comment


          • #6
            tbender,

            I would check to make sure you are using the "form:form" MVC tag (<form:form method="PUT"..>) in your form. That creates a hidden field named "_method", which I believe Spring MVC uses to detect PUT requests.

            If you are using a single form for POST/PUT, you will need to create that hidden field another way.

            (This may not be the problem in your case, but it would cause the symptoms you describe, making it seem as if your PUT is getting turned into a POST.)

            Comment


            • #7
              Thanks mikej.

              AFAIR I use the spring form:from tag and the method is set to put.
              I'll see if I can get the log output.

              Comment


              • #8
                Originally posted by tbender View Post
                Thanks mikej.

                AFAIR I use the spring form:from tag and the method is set to put.
                I'll see if I can get the log output.

                Don't you have to put in the hidden field for _method yourself? Just vaguely recollect seeing it in the docs, but is in the far distance of my memory, so I can be very inaccurate here.

                Very cool news about ROO-8 and the possible new looks.

                Mark

                Comment


                • #9
                  Configuration and Log output

                  Hi here is my secruity configuration (auth mechanism omitted)

                  Code:
                  	<!-- HTTP security configurations -->
                      <http auto-config="true" use-expressions="true">
                      	<form-login login-processing-url="/static/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t"/>
                          <logout logout-url="/static/j_spring_security_logout"/>
                          
                          <!-- Configure these elements to secure URIs in your application -->
                  <!--        <intercept-url pattern="/choice/**" access="hasRole('ROLE_ADMIN')"/>--><!--
                          <intercept-url pattern="/member/**" access="isAuthenticated()" />
                          --><intercept-url pattern="/resources/**" access="permitAll" />
                          <intercept-url pattern="/static/**" access="permitAll" />
                          <intercept-url pattern="/login" access="permitAll" />
                          <intercept-url pattern="/**" access="isAuthenticated()" />
                      </http>
                  Here is the controller method, that should be used:

                  Code:
                  	@RequestMapping(method = RequestMethod.PUT)    
                      public String update(@Valid ScriptFile scriptFile, BindingResult result, ModelMap modelMap, HttpServletRequest request) {    
                          if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");        
                          if (result.hasErrors()) {        
                              modelMap.addAttribute("scriptFile", scriptFile);            
                              modelMap.addAttribute("showcases", ShowCase.findAllShowCases());            
                              return "scriptfile/update";            
                          }
                          setFileParameters(scriptFile, request);
                          scriptFile.merge();        
                          return "redirect:/scriptfile/" + scriptFile.getId();        
                      }
                  And here is waht the log says:
                  Code:
                  Converted URL to lowercase, from: '/scriptfile/3'; to: '/scriptfile/3'
                  Candidate is: '/scriptfile/3'; pattern is /resources/**; matched=false
                  Candidate is: '/scriptfile/3'; pattern is /static/**; matched=false
                  Candidate is: '/scriptfile/3'; pattern is /login; matched=false
                  Candidate is: '/scriptfile/3'; pattern is /**; matched=true
                  Secure object: FilterInvocation: URL: /scriptfile/3; Attributes: [isAuthenticated()]
                  Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@bad9b5a1: Principal: org.springframework.security.core.userdetails.User@0: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffc7f0c: RemoteIpAddress: 127.0.0.1; SessionId: 127lj3enf736d; Granted Authorities: ROLE_ADMIN
                  Voter: org.springframework.security.web.access.expression.WebExpressionVoter@73db92, returned: 1
                  Authorization successful
                  RunAsManager did not change Authentication object
                  /scriptfile/3 reached end of additional filter chain; proceeding with original chain
                  Using EntityManagerFactory 'entityManagerFactory' for OpenEntityManagerInViewFilter
                  Returning cached instance of singleton bean 'entityManagerFactory'
                  Opening JPA EntityManager in OpenEntityManagerInViewFilter
                  DispatcherServlet with name 'sc' processing POST request for [/sc/app/scriptfile/3]
                  Found multipart file [file] of size 1167 bytes with original filename [Lesson-1A-SQL-Injection.html], stored in memory
                  Matching patterns for request [/scriptfile/3] are [/scriptfile/{id}, /scriptfile/**/, /scriptfile/**]
                  Mapping [/scriptfile/3] to handler 'com.mycompany.sc.web.ScriptFileController@19a13e5'
                  Resolving exception from handler [com.mycompany.sc.web.ScriptFileController@19a13e5]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
                  Resolving to view 'uncaughtException' for exception of type [org.springframework.web.HttpRequestMethodNotSupportedException], based on exception mapping [.lang.Exception]
                  Exposing Exception as model attribute 'exception'
                  Handler execution resulted in exception - forwarding to resolved error view: ModelAndView: reference to view with name 'uncaughtException'; model is {exception=org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported}
                  org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
                  	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodResolver.resolveHandlerMethod(AnnotationMethodHandlerAdapter.java:567)
                  Here is the form-Tag as I use it (ony small modification from what roo generated):
                  Code:
                  <form:form action="${form_url}" method="PUT" modelAttribute="scriptFile" enctype="multipart/form-data">
                  As you can see the form states PUT but the logoutput shows that spring-mvc is trying to map a POST method. I'll check the requests again with firebug.
                  Last edited by tbender; Feb 22nd, 2010, 08:28 AM.

                  Comment


                  • #10
                    Checked with firebug

                    Hi folks,

                    Just checked the requests using firebug.

                    I can see that the form sends a HTTP-Post request with the following content:

                    Code:
                    Content-Type: multipart/form-data; boundary=---------------------------16652697611625305771130515920
                    
                    5
                    
                    Content-Length: 2554
                    
                    -----------------------------166526976116253057711305159205
                    
                    Content-Disposition: form-data; name="_method"
                    
                    PUT
                    
                    -----------------------------166526976116253057711305159205
                    
                    Content-Disposition: form-data; name="name"
                    
                    ConfiguredAccounts
                    
                    -----------------------------166526976116253057711305159205
                    
                    Content-Disposition: form-data; name="showcase"
                    
                    1
                    
                    -----------------------------166526976116253057711305159205
                    
                    Content-Disposition: form-data; name="file"; filename="Default-Config-Accounts.html"
                    Last edited by tbender; Feb 24th, 2010, 05:52 AM.

                    Comment


                    • #11
                      Since this seems due to a currently unfixed bug in Spring I added a workaround using POST and a different path so it does not confilct with my other POST-Mappings.

                      Code:
                      	/* Usually you would use a mapping to HTTP-PUT in a REST-Application.
                      	*Since there is a BUG with multipart-requests and HiddenHttpMethodFilter
                      	*we use a different path and the POST-Method here
                      	*https://jira.springsource.org/browse/SPR-6594
                      	*/
                      	@RequestMapping(value="/scriptfile/{id}/update", method = RequestMethod.POST)    
                          public String update(@Valid ScriptFile scriptFile,
                          							BindingResult result,
                          							ModelMap modelMap, HttpServletRequest request) {    
                              if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");        
                              if (result.hasErrors()) {        
                                  modelMap.addAttribute("scriptFile", scriptFile);            
                                  modelMap.addAttribute("showcases", ShowCase.findAllShowCases());            
                                  return "scriptfile/update";            
                              }
                              setFileParameters(scriptFile, request);
                              scriptFile.merge();        
                              return "redirect:/scriptfile/" + scriptFile.getId();        
                          }

                      Comment


                      • #12
                        @tbender,

                        Thanks for sharing your research here. I have linked this forum thread to the ROO-442 feature request. This is something I'll be looking into soon.

                        Cheers,
                        Stefan

                        Comment


                        • #13
                          You're welcome. I love roo and especially how fast it is progressing :-)
                          How about the kangaroo-app? ;-)

                          Originally posted by Stefan Schmidt View Post
                          @tbender,

                          Thanks for sharing your research here. I have linked this forum thread to the ROO-442 feature request. This is something I'll be looking into soon.

                          Cheers,
                          Stefan

                          Comment


                          • #14
                            I'm still having problems getting a multipart upload working with a PUT request
                            (see latest comments on https://jira.springsource.org/browse/SPR-6594)

                            Did anyone get an upload to work by using the PUT method?

                            Comment


                            • #15
                              Any progress on this?

                              I have checked jira issue, and it seem to be fixed on 3.0.2.

                              I have 3.0.3 version of spring and same/similar issue.

                              I am new to spring MVC, so application is simple, and has simple security (guess it is relevant).

                              So, although I put PUT as method, it ends up as POST, and I get error

                              "Request method 'POST' not supported".

                              Comment

                              Working...
                              X