0

I'm trying to implement primefaces fileupload with imageCropper for change user's avatar under https.
I upload the image and save it into application server's temp folder.
I served the uploaded image into primefaces imageCropper with a WebServlet from server's temp path

When I use http everything works fine, but when I turned into https I have error {0}: Conversion error occurred.

This is my code:

xhtml code

 <p:imageCropper
    id="avatarImage"
    image="https://#{request.serverName}:#{request.serverPort}#{request.contextPath}/reports/#{UserpreferencesBean.imageFilePath}"
    value="#{UserpreferencesBean.croppedImage}"
    aspectRatio="1.0" initialCoords="225,75,300,125"
    boxWidth="400"
    boxHeight="400"
    minSize="90,90"/>
  <br/>

   <p:commandButton id="cropButton"
     value="Crop"
     action="#{UserpreferencesBean.crop()}"
     update="form:messages image avatarImage avatarForm"
     icon="ui-icon-scissors"/>

Bean code

public void crop() throws IOException {
    avatarImage = new DefaultStreamedContent(null);
    avatarImage = new DefaultStreamedContent(new ByteArrayInputStream(croppedImage.getBytes()));

    in = new ByteArrayInputStream(croppedImage.getBytes());
    avatarByteArray = croppedImage.getBytes();

    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success", "Cropping finished."));
}

WebServlet code

@WebServlet("/reports/*")
public class ImageServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String filename = request.getPathInfo().substring(1);
    File file = new File(System.getProperty("jboss.server.temp.dir"), filename);
    response.setHeader("Content-Type", getServletContext().getMimeType(filename));
    response.setHeader("Content-Length", String.valueOf(file.length()));
    response.setHeader("Content-Disposition", "inline; filename="+File.separator + filename + File.separator );
    Files.copy(file.toPath(), response.getOutputStream());
}

}

Some notes
-> My ssl is not valid. I use a self-sign certificate
-> My application server is Wildfly 16

tsotzolas
  • 387
  • 1
  • 10
  • 1
    Narrow things down, use static non-uplpaded file with a fixed url in the `image` attribute ). Does it still fail? Then reduce the code in your answer. Does it fail using an image from another site (not using a servlet)? – Kukeltje Jun 13 '19 at 18:35
  • If I use a static url from my servlet with ssl, it doesn't work. If I put an image from the internet it works. But the image from the internet has a valid ssl certificate. I don't know if the ssl make the problem or my servlet. – tsotzolas Jun 13 '19 at 19:16
  • Then find out... effectivel it is not upload related and do you get the same error with static https url? – Kukeltje Jun 13 '19 at 19:45
  • The upload image is ok, because i can see the uploaded image in the temp folder that I upload the image. If I put static https url with the servlet I get the same error. `Conversion error occurred` I think that the problem is the way that I served the image in browser. How I can serve the image from specific filepath? – tsotzolas Jun 13 '19 at 20:11

1 Answers1

1

Finally, I found the solution. The problem is the self-sign certificate. The solution is to trust in java the untrusted certificate. You can just this code in a listener at the start of the application and will trust all the certificates.

 private static class TrustAllManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
    }

    @Override
    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}
    public static void initTrustAllClient() {

        try {
            TrustManager[] trustAll = new TrustManager[]{new TrustAllManager()};

            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAll, new SecureRandom());

            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HostnameVerifier allHostValid = new HostnameVerifier() {
                @Override
                public boolean verify(String string, SSLSession ssls) {
                    return true;
                }
            };
            HttpsURLConnection.setDefaultHostnameVerifier(allHostValid);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Some links for that
Trusting all certificates using HttpClient over HTTPS
https://gist.github.com/michalbcz/4170520


Other workaround(not very good) is to exclude the WebServlet URL from SSL security and I served the image without https.

So all the application is with https except image servlet.

I still believe that the problem is the self-sign certificate.

 <security-constraint>
    <web-resource-collection>
        <web-resource-name>SecureResource</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>
<security-constraint>
    <web-resource-collection>
        <web-resource-name>Non-SecureResource</web-resource-name>
        <url-pattern>/reports/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
</security-constraint>
tsotzolas
  • 387
  • 1
  • 10
  • Mixed http and https content might result in warnings in browsers! – Kukeltje Jun 15 '19 at 16:59
  • This is true. But is the only way for me to have something that is working. – tsotzolas Jun 16 '19 at 06:28
  • Adding a 'trust all' hostnameverifier is bad practice and should only be used in test situations. Just add the self-signed certificate truststore. That is the good solution. – Kukeltje Jun 18 '19 at 16:18