2017-08-15 46 views
1

我的工作中,我得請求負載,解密,檢查它是否是一個有效的JSON和過濾器,如果是去與鏈和去我服務。事情是,到目前爲止,我還沒有找到一種方法來重寫身體。爲什麼我要重寫它?由於服務需要一個JSON和要求在體內的加密文本,一旦我解密我想身體要解密的JSON。另外,一旦我從服務中返回,我應該重寫響應以使json加密。我讀過很多論壇和問題,但無法獲得有效的解決方案。如何重寫POST請求的身體上的HttpServletRequest

這裏是我的代碼:

RequestLoginFilter.java

@WebFilter("/RequestLoginFilter") 
public class RequestLoginFilter implements Filter{ 

    protected final static Log logger = LogFactory.getLog(RequestLoginFilter.class); 

    private ServletContext context; 

    private CryptoUtil crypto; 

    public void init(FilterConfig fConfig) throws ServletException { 
     this.context = fConfig.getServletContext(); 
     this.context.log("RequestLoggingFilter initialized"); 
    } 

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
//  use wrapper to read multiple times the content 
     AuthenticationRequestWrapper req = new AuthenticationRequestWrapper((HttpServletRequest) request); 
     HttpServletResponse resp = (HttpServletResponse) response; 

     String payload = req.getPayload(); 
     try { 
      String decryptedPayload = crypto.decrypt(payload); 
      JSONUtils.convertJSONStringToObject(decryptedPayload, LoginTokenTO.class); 
     } catch (GeneralSecurityException e) { 
      logger.error("Error when trying to decrypt payload '"+payload+"'"); 
      throw new ServletException("Error when trying to decrypt payload '"+payload+"'", e); 
     } 
     chain.doFilter(req, resp); 
     System.out.println("a ver"); 
    } 

    @Override 
    public void destroy() { 
     // TODO Auto-generated method stub 

    } 

} 

而且還包裝,以防萬一:

AuthenticationRequestWrapper.java

public class AuthenticationRequestWrapper extends HttpServletRequestWrapper { 

    protected final static Log logger = LogFactory.getLog(AuthenticationRequestWrapper.class); 

    private final String payload; 

    public AuthenticationRequestWrapper (HttpServletRequest request) throws AuthenticationException { 
     super(request); 

     // read the original payload into the payload variable 
     StringBuilder stringBuilder = new StringBuilder(); 
     BufferedReader bufferedReader = null; 
     try { 
      // read the payload into the StringBuilder 
      InputStream inputStream = request.getInputStream(); 
      if (inputStream != null) { 
       bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 
       char[] charBuffer = new char[128]; 
       int bytesRead = -1; 
       while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { 
        stringBuilder.append(charBuffer, 0, bytesRead); 
       } 
      } else { 
       // make an empty string since there is no payload 
       stringBuilder.append(""); 
      } 
     } catch (IOException ex) { 
      logger.error("Error reading the request payload", ex); 
      throw new AuthenticationException("Error reading the request payload", ex); 
     } finally { 
      if (bufferedReader != null) { 
       try { 
        bufferedReader.close(); 
       } catch (IOException iox) { 
        // ignore 
       } 
      } 
     } 
     payload = stringBuilder.toString(); 
    } 

    @Override 
    public ServletInputStream getInputStream() throws IOException { 
     final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(payload.getBytes()); 
     ServletInputStream inputStream = new ServletInputStream() { 
      public int read() 
       throws IOException { 
       return byteArrayInputStream.read(); 
      } 
     }; 
     return inputStream; 
    } 

    public String getPayload() { 
     return payload; 
    } 
} 
這裏

希望有人知道我怎樣才能得到這個工作。

在此先感謝你們。

回答

1

雖然你問可能是技術上是可行的,它聽起來並不像正確的方法給我。

你需要的是傳入的請求(端點)和服務之間的坐在一個安全層。重寫請求的主體是一件很奇怪的事情(這可能解釋了爲什麼你有問題)。是否有理由讓您在Filter中完成此操作?畢竟,filters旨在過濾請求,而不是重寫它們;)

更合理/透明的解決方案是讓您的端點接受所有傳入請求,在將請求傳遞到服務層之前解密並驗證它們。事情是這樣的:

public void handleRequest(Request request) { 
    try { 
     IncomingRequest x = securityManager.decrypt(request); 
     Response r = myService.handleRequest(x); 
     handleResponse(securityManager.encrypt(r)); 
    }catch(InvlidateMessage x) { 
     handleInvalidMessage... 
    }catch(BusinessException x) { 
     handleBusinessException... 
    } 
}