Wednesday, August 7, 2013

Avoiding "javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated" in HttpClient

When developing an application that uses https, your test server doesn't have a valid SSL certificate. Or sometimes the web site is using a self-signed certificate or the web site is using free SSL certificate. So if you try to connect to the server using Apache HttpClient, you will get a exception telling that the "peer not authenticated". Though it is not a good practice to trust all the certificates in a production software, you may have to do so according to the situation.
This solution resolves the exception caused by "peer not authenticated".

But before we go to the solution, I must warn you that this is not a good idea for a production application. This will violate the purpose of using a security certificate. So unless you have a good reason or if you are sure that this will not cause any problem, don't use this solution.

Normally you create a HttpClient like this.
HttpClient httpclient = new DefaultHttpClient();

But you have to change the way you create the HttpClient.

First you have to create a class extending org.apache.http.conn.ssl.SSLSocketFactory.

import org.apache.http.conn.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class MySSLSocketFactory extends SSLSocketFactory {
         SSLContext sslContext = SSLContext.getInstance("TLS");

    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);

        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}


Then create a method like this.
public HttpClient getNewHttpClient() {
   try {
       KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
       trustStore.load(null, null);

       SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
       sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

       HttpParams params = new BasicHttpParams();
       HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
       HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

       SchemeRegistry registry = new SchemeRegistry();
       registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
       registry.register(new Scheme("https", sf, 443));

       ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

       return new DefaultHttpClient(ccm, params);
   } catch (Exception e) {
       return new DefaultHttpClient();
   }
}

Then you can create the HttpClient.
HttpClient httpclient = getNewHttpClient();

If you are trying to send a post request to a login page the rest of the code would be like this.
private URI url = new URI("url of the action of the form");
HttpPost httppost =  new HttpPost(url);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();  
nameValuePairs.add(new BasicNameValuePair("username", "user"));  
nameValuePairs.add(new BasicNameValuePair("password", "password"));
try {
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

You get the html page to the InputStream. Then you can do whatever you want with the returned html page.

But here you will face a problem. If you want to manage a session using cookies, you will not be able to do it with this method. If you want to get the cookies, you will have to do it via a browser. Then only you will receive cookies.

Sunday, August 4, 2013

3D in Your Web Browser

Rendering a 3D image was a difficult task in early days. But now you can render a 3D image even in your web browser. Using HTML 5 with CSS 3 you can make 3D images in your web browser. But if you use JavaScript with HTML 5 you can do amazing things. But if you choose a proper JavaScript framework you will be amazed what it can do in a web browser. One such framework is three.js
three.js allows you to choose how you  render the image on your web browser. You can choose from WebGL of Canvas. WebGL uses graphics processor of your computer. So it gives you a good experience. But to use WebGL, you must use Windows operating system and Google chrome or Firefox. But Google chrome guarantees you the best user experience. But you can use Canvas in most of the operating systems and most of the web browsers which support HTML 5. But I must say that Canvas is bit slow when rendering the image. If you are using complex shapes you are advised to use WebGL renderer.
You can download three.js framework from http://threejs.org/ All you need to do is import three.js JavaScript file to your HTML page. If you need custom functionality, you have to add relevant JavaScript files that is needed.
Then you have to add a JavaScript to your HTML page. This may include two functions. init for initialization and animation for custom animations like handling the keyboard inputs.
In your HTML code add
<div id="output"></div>
Then in the JavaScript add this code.(You have to add jQuery to ease some implementations)

var scene = new THREE.Scene();
var container = $('#output');

Then get the detector.js from https://github.com/mrdoob/three.js/blob/master/examples/js/Detector.js and import it also to the page. Then,

var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var renderer;
if (Detector.webgl)
       renderer = new THREE.WebGLRenderer({antialias: true});
else
       renderer = new THREE.CanvasRenderer();
renderer.setClearColorHex(0xffffff, 1);
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container.append(renderer.domElement);
will detect whether you have WebGL renderer or not and create the necessary renderer for you will add it to the div you have previously created.

Then create the camera like this
var VIEW_ANGLE = 80, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 50, FAR = 200000;
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.y = 0;
camera.position.z = RACK_THICKNESS*RACKS*3;
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(camera);

Now you have done the basic initialization. Then you have to add the objects you need to the scene. If you need to a box with a hole in the middle,

var object = new THREE.Object3D();
var shape1 = new THREE.Shape();
shape1.moveTo(50, 50);
shape1.lineTo(-50, 50);
shape1.lineTo(-50, -50);
shape1.lineTo(50, -50);
shape1.lineTo(50, 50);

var hole1 = new THREE.Path();
hole1.moveTo(40, 40);
hole1.lineTo(-40, 40);
hole1.lineTo(-40, -40);
hole1.lineTo(40, -40);
hole1.lineTo(40, 40);
shape1.holes.push(hole1);

 var extrusionSettings = {
         amount: 100,
         bevelEnabled: true,
         bevelThickness: 0.5,
         bevelSize: 0.5,
         bevelSegments: 8,
         material: 0,
         extrudeMaterial: 1
};
var geometry1 = new THREE.ExtrudeGeometry(shape1, extrusionSettings);
var materialFront = new THREE.MeshLambertMaterial({
        color: 0xffff00,
        ambient: 0xffff00
});
var materialSide = new THREE.MeshLambertMaterial({
        color: 0xff8800,
        ambient: 0xff8800
});
var materials = [materialFront, materialSide];
var material = new THREE.MeshFaceMaterial(materials);
var mesh1 = new THREE.Mesh(geometry1, material);
mesh1.position.set(0, 50, 0);
object.add(mesh1);
scene.add(object);

This will create the object and add it to the scene. All this have to be done in the init function. Then in the animate function,

function animate() {
                requestAnimationFrame(animate);

                var delta = clock.getDelta();
                var moveDistance = 200 * delta;
                var rotateAngle = Math.PI / 2 * delta;

                if (keyboard.pressed("right")) {
                    object.position.x -= moveDistance;
                }
                if (keyboard.pressed("left")) {
                    object.position.x += moveDistance;
                }
                if (keyboard.pressed("up")) {
                    object.position.y -= moveDistance;
                }
                if (keyboard.pressed("down")) {
                    object.position.y += moveDistance;
                }

                var rotation_matrix_object = new THREE.Matrix4().identity();
                if (keyboard.pressed("A")) {
                    rotation_matrix_object = new THREE.Matrix4().makeRotationY(rotateAngle);
                }
                if (keyboard.pressed("D")) {
                    rotation_matrix_object = new THREE.Matrix4().makeRotationY(-rotateAngle);
                }
                if (keyboard.pressed("W")) {
                    rotation_matrix_object = new THREE.Matrix4().makeRotationX(rotateAngle);
                }
                if (keyboard.pressed("S")) {
                    rotation_matrix_object = new THREE.Matrix4().makeRotationX(-rotateAngle);
                }
                if (keyboard.pressed("A") || keyboard.pressed("D") || keyboard.pressed("W") || keyboard.pressed("S"))
                {
                    object.matrix.multiply(rotation_matrix_object);
                    object.rotation.setEulerFromRotationMatrix(object.matrix);
                }
}

This will repeatedly render the scene and add the basic keyboard functionality. You have to import THREEx.KeyboardState.js to the page. As you have created the 2 functions, all you have to do is to call these 2 functions at the start of the JavaScript.

Most of these are self explanatory. So if you know the basics of programming, you will find it easy to understand what is happening in the code.



This a sample image created using three.js framework. Combining these simple shapes you can create lot more complex shapes.


You can find more examples from http://stemkoski.github.io/Three.js/