2012-05-14 32 views
7

我無法在servlet multipart post期間訪問Spring Security信息。春季安全信息可在常規獲取和後期方法中使用,但不適用於多部分後期方法。我嘗試通過SecurityContextHolder.getContext()。getAuthentication()並通過一個訪問SecurityContextHolder.getContext()。getAuthentication()的注入服務直接訪問此安全信息,但嘗試失敗。在servlet multipart post期間無法訪問Spring Security信息

我還實施了HttpRequestHandler和ServletWrappingController。再次,我能夠成功地向他們注入spring bean並訪問Spring Security信息以獲取常規獲取和發佈方法,但是我無法訪問Spring Security信息以查看多部分帖子。我知道Spring 3.0中內置了新的MultiPart功能,但因爲我們的網站需要完全訪問文件上傳流,所以我無法使用它們。出於這個原因,我專注於HttpServlet,HttpRequestHandler和ServletWrappingController。

我張貼在這裏的代碼寫入到解決我面臨着一個多上載過程中不被使用的安全信息這一特定問題的所有測試代碼(並不意味着要生產質量)。它用於HttpServlet。

請讓我知道如果有什麼我做錯了。或者,如果沒有解決方法或更好的方法來完成可以訪問Spring Security信息的分段上傳,同時保持對文件上傳流的訪問?任何人可以提供這個問題的援助將不勝感激!

下面是測試servlet代碼。下面的評論,什麼可行,什麼不基於使用的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{ 
      //... 
     } 


    } 

} 

這裏是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> 
+0

你可以添加,顯示春季安全配置web.xml中的一部分? – Ritesh

+0

爲什麼在web.xml而不是在Spring配置中將請求映射到'UploadServlet'? –

回答

0

這可以幫助你,如果你使用Spring MVC:通過SecurityContextHolder中提供

{ 
    @RequestMapping(method = RequestMethod.POST, value = "/some/post/url") 
    public void postFile(MultipartHttpServletRequest request) { 
    MultipartFile multipartFile = request.getFileMap().get("fileControlName"); 
    ... 
    } 
} 
+0

你應該解釋如何解決這個問題。 –

0

這可能是值得檢查你的客戶是如何執行的多部分後,您使用的是不同的機制/庫您的標準交?

如果我猜我會說你的客戶端代碼沒有爲多部分用例正確驗證。

E.g.使用普通帖子的標準Java和多部分帖子的Apache庫,並在使用Apache時忘記設置適當的http標頭。

2

我可以確認的是,Spring 3.0.x和春季安全3.0.x的與多崗位協同工作,以及他們與其他類型的請求工作。我遇到了類似的行爲,在我們的例子中,由於我們在過濾器映射中的錯誤,安全過濾器沒有被應用到請求中。

你可以發佈你的網站的部分。定義安全過濾器的xml,並將其映射到所需的路徑?