I cannot access Spring security information during a multi-page servlet message. Spring security information is available during regular receive and publish methods, but is not available for the multipart post method. I tried unsuccessfully to access this security information directly through SecurityContextHolder.getContext (). GetAuthentication () and through an embedded service that accesses SecurityContextHolder.getContext (). GetAuthentication ().
I also implemented the HttpRequestHandler and ServletWrappingController. Once again, I was able to successfully inject Spring beans into them and access Spring security information for regular retrieval and publishing methods, but I was not able to access Spring security information for multi-page posts. I know that there are new MultiPart features built into Spring 3.0, but since our website will require full access to the file download stream, I will not be able to use them. For this reason, I focus on the HttpServlet, HttpRequestHandler and ServletWrappingController.
The code that I post here is all the test codes written to solve this particular problem that I am facing, and the security information is not available during multi-page downloads (not to ensure product quality). This is for the HttpServlet.
Please let me know if I am doing something wrong. Or, if not, if there is a workaround or a better way to do multi-page downloads with access to Spring security information while maintaining access to the file download stream? Any help anyone with this problem can offer would be greatly appreciated!
The following is the code for the test servlet. The comments below about what works and what doesn't are based on the user logged in to the website using Spring Security 3.1:
//many import statements not displayed import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.context.support.SpringBeanAutowiringSupport; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; public class UploadServlet extends HttpServlet { public void service(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { super.service(req, res); } public void init(ServletConfig config) throws ServletException { super.init(config); SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext()); } //The following is always injected and available //however, it only returns valid security information for regular get and post methods, //not for multipart post methods @Autowired private CustomUserService customUserService; //The following is always injected and available and always returns the expected data @Autowired private GuideService guideService; //the following does not work when the client issues a multipart post, it does work for non-multipart public boolean getAuthenticated(){ boolean authorized = false; for (GrantedAuthority authority : SecurityContextHolder.getContext().getAuthentication().getAuthorities()) { if(authority.getAuthority().equals("ROLE_USER") || authority.getAuthority().equals("ROLE_ADMIN")) { authorized = true; break; } } return authorized; } //The following test get method works fine protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if(getAuthenticated()){ PrintWriter out = resp.getWriter(); out.write("<h1>Guide Info</h1><br/>"); Guide guide = guideService.findById(2l); out.write(guide.getName() + "<br/>"); out.write(guide.getDescription() + "<br/>"); out.write("UserName: " + customUserService.getCurrentUser().getUsername() + "<br/>"); } else{ PrintWriter out = resp.getWriter(); out.write("<h1>You're not authorized</h1><br/>"); } } //This post method protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //the following always works, whether the clients posts using multipart or not String guideName = guideService.findById(2l).getName(); //the following does not work when the client issues a multipart post, it does work for non-multipart String userName = customUserService.getCurrentUser().getUsername(); //the following does not work when the client issues a multipart post, it does work for non-multipart if(getAuthenticated()){ String responseString = RESP_SUCCESS; boolean isMultipart = ServletFileUpload.isMultipartContent(req); if (isMultipart) { ServletFileUpload upload = new ServletFileUpload(); //commmons fileupload code // Not a multi-part MIME request. else { //... } //... } else{ //... } } }
Here is the relevant part of web.xml:
<servlet> <servlet-name>fgm</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/spring/webmvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>fgm</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <servlet> <servlet-name>UploadServlet</servlet-name> <servlet-class>com.guides.servlet.UploadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UploadServlet</servlet-name> <url-pattern>/upload</url-pattern> </servlet-mapping>