天天看点

Android HTTPS验证和添加http头信息token认证

 实现https信任所有证书的方法

android平台上经常有使用https的需求,对于https服务器使用的根证书是受信任的证书的话,实现https是非常简单的,直接用httpclient库就行了,与使用http几乎没有区别。但是在大多数情况下,服务器所使用的根证书是自签名的,或者签名机构不在设备的信任证书列表中,这样使用httpclient进行https连接就会失败。解决这个问题的办法有两种,一是在发起https连接之前将服务器证书加到httpclient的信任证书列表中,这个相对来说比较复杂一些,很容易出错;另一种办法是让httpclient信任所有的服务器证书,这种办法相对来说简单很多,但安全性则差一些,但在某些场合下有一定的应用场景。这里要举例说明的就是后一种方法:实例化httpclinet对象时要进行一些处理主要是绑定https连接所使用的端口号,这里绑定了443和8443:

[java] view

plaincopy

schemeregistry schemeregistry = new schemeregistry();  

schemeregistry.register(new scheme("https",  

                    new easysslsocketfactory(), 443));  

                    new easysslsocketfactory(), 8443));  

clientconnectionmanager connmanager = new threadsafeclientconnmanager(params, schemeregistry);  

httpclient httpclient = new defaulthttpclient(connmanager, params);  

上面的easysslsocketfactory类是我们自定义的,主要目的就是让httpclient接受所有的服务器证书,能够正常的进行https数据读取。相关代码如下:

public class easysslsocketfactory implements socketfactory,  

        layeredsocketfactory {  

    private sslcontext sslcontext = null;  

    private static sslcontext createeasysslcontext() throws ioexception {  

        try {  

            sslcontext context = sslcontext.getinstance("tls");  

            context.init(null, new trustmanager[] { new easyx509trustmanager(  

                    null) }, null);  

            return context;  

        } catch (exception e) {  

            throw new ioexception(e.getmessage());  

        }  

    }  

    private sslcontext getsslcontext() throws ioexception {  

        if (this.sslcontext == null) {  

            this.sslcontext = createeasysslcontext();  

        return this.sslcontext;  

    public socket connectsocket(socket sock, string host, int port,  

            inetaddress localaddress, int localport, httpparams params)  

            throws ioexception, unknownhostexception, connecttimeoutexception {  

        int conntimeout = httpconnectionparams.getconnectiontimeout(params);  

        int sotimeout = httpconnectionparams.getsotimeout(params);  

        inetsocketaddress remoteaddress = new inetsocketaddress(host, port);  

        sslsocket sslsock = (sslsocket) ((sock != null) ? sock : createsocket());  

        if ((localaddress != null) || (localport > 0)) {  

            // we need to bind explicitly  

            if (localport < 0) {  

                localport = 0; // indicates "any"  

            }  

            inetsocketaddress isa = new inetsocketaddress(localaddress,  

                    localport);  

            sslsock.bind(isa);  

        sslsock.connect(remoteaddress, conntimeout);  

        sslsock.setsotimeout(sotimeout);  

        return sslsock;  

    public socket createsocket() throws ioexception {  

        return getsslcontext().getsocketfactory().createsocket();  

    public boolean issecure(socket socket) throws illegalargumentexception {  

        return true;  

    public socket createsocket(socket socket, string host, int port,  

            boolean autoclose) throws ioexception, unknownhostexception {  

        return getsslcontext().getsocketfactory().createsocket(socket, host,  

                port, autoclose);  

    // -------------------------------------------------------------------  

    // javadoc in org.apache.http.conn.scheme.socketfactory says :  

    // both object.equals() and object.hashcode() must be overridden  

    // for the correct operation of some connection managers  

    public boolean equals(object obj) {  

        return ((obj != null) && obj.getclass().equals(  

                easysslsocketfactory.class));  

    public int hashcode() {  

        return easysslsocketfactory.class.hashcode();  

}  

public class easyx509trustmanager implements x509trustmanager {  

    private x509trustmanager standardtrustmanager = null;  

    public easyx509trustmanager(keystore keystore)  

            throws nosuchalgorithmexception, keystoreexception {  

        super();  

        trustmanagerfactory factory = trustmanagerfactory  

               .getinstance(trustmanagerfactory.getdefaultalgorithm());  

        factory.init(keystore);  

        trustmanager[] trustmanagers = factory.gettrustmanagers();  

        if (trustmanagers.length == 0) {  

            throw new nosuchalgorithmexception("no trust manager found");  

        this.standardtrustmanager = (x509trustmanager) trustmanagers[0];  

    public void checkclienttrusted(x509certificate[] certificates,  

            string authtype) throws certificateexception {  

        standardtrustmanager.checkclienttrusted(certificates, authtype);  

    public void checkservertrusted(x509certificate[] certificates,  

        if ((certificates != null) && (certificates.length == 1)) {  

            certificates[0].checkvalidity();  

        } else {  

            standardtrustmanager.checkservertrusted(certificates, authtype);  

    public x509certificate[] getacceptedissuers() {  

        return this.standardtrustmanager.getacceptedissuers();  

}  

plaincopyprint?

Android HTTPS验证和添加http头信息token认证
Android HTTPS验证和添加http头信息token认证

        schemeregistry.register(new scheme("http", plainsocketfactory  

                .getsocketfactory(), 80));  

        sslsocketfactory sf = sslsocketfactory.getsocketfactory();  

            keystore truststore = keystore.getinstance(keystore  

                    .getdefaulttype());  

            truststore.load(null, null);  

            sf = new sslsocketfactoryex(truststore);  

            sf.sethostnameverifier(sslsocketfactory.allow_all_hostname_verifier);  

            // 允许所有主机的验证  

            log.e("erro", "sslsocketfactory error");  

        schemeregistry.register(new scheme("https", sf, 443));  

        threadsafeclientconnmanager cm = new threadsafeclientconnmanager(  

                httpparams, schemeregistry);  

defaulthttpclient httpclient = new defaulthttpclient(cm, httpparams);  

上面的sslsocketfactoryex类主要目的就是让httpclient接受所有的服务器证书,能够正常的进行https数据读取。相关代码如下:

Android HTTPS验证和添加http头信息token认证
Android HTTPS验证和添加http头信息token认证

class sslsocketfactoryex extends sslsocketfactory {  

        sslcontext sslcontext = sslcontext.getinstance("tls");  

        public sslsocketfactoryex(keystore truststore)  

                throws nosuchalgorithmexception, keymanagementexception,  

                keystoreexception, unrecoverablekeyexception {  

            super(truststore);  

            trustmanager tm = new x509trustmanager() {  

                @override  

                public java.security.cert.x509certificate[] getacceptedissuers() {  

                    return null;  

                }  

                public void checkclienttrusted(  

                        java.security.cert.x509certificate[] chain,  

                        string authtype)  

                        throws java.security.cert.certificateexception {  

                public void checkservertrusted(  

            };  

            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);  

        public socket createsocket() throws ioexception {  

            return sslcontext.getsocketfactory().createsocket();  

添加http头信息token认证

有时候服务器端需要传递token来验证请求来源是否是受信任的,以增强安全性:

重点是有些服务器要求将token转化成base64编码。

于是  string token ="basic " +

base64.encodetostring("your token".getbytes(), base64.no_wrap);

注意,参数是 base64.no_wrap,而不是base64.default

。而否则会返回 “400 bad request”,而得不到数据。

继续阅读