简体   繁体   中英

NodeJS + Android SSL Authentication

I have no idea how to debug this, been at this for a while now, any pointers would be appreciated.

I am trying out ssl/tls authentication between an Android app and a Nodejs server. I am running into this error message when I run the android app:

10-31 23:33:58.260: D/ExampleActivity(26199): Response code: 401
10-31 23:34:05.901: W/DefaultRequestDirector(26199): Authentication error: Unable to respond to any of these challenges: {}

Note that I have commented out the client authentication parts, and just trying to get basic SSL authentication working. Even that gives me the same warning/error.

NodeJs - Server.js

var https = require('https'),
    fs = require('fs');

var options = {
    key: fs.readFileSync('certs/server_key.pem'),
    cert: fs.readFileSync('certs/server.pem'),
   // ca: [fs.readFileSync('certs/client.pem')],
    passphrase: '33333',
   // requestCert: true,
   // rejectUnauthorized: false
};

https.createServer(options, function (req, res) {
    if (req.client.authorized) {
        res.writeHead(200, {"Content-Type": "application/json"});
        res.end('{"status":"approved"}');
    } else {
        res.writeHead(401, {"Content-Type": "application/json"});
        res.end('{"status":"denied"}');
    }
}).listen(8000);

Android

public class SecureHttpClient extends DefaultHttpClient {
    private String ks = "11111";
    private String ts = "22222";
    private Context context;

    public SecureHttpClient(final Context context) {
        super();
        this.context = context;
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        SSLSocketFactory factory = newSslSocketFactory();
        factory.setHostnameVerifier((X509HostnameVerifier) SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        registry.register(new Scheme("https", factory, 443));
        HttpParams httpParams = new BasicHttpParams();
        return new SingleClientConnManager(httpParams, registry);
    }

    private SSLSocketFactory newSslSocketFactory() {
        try {
            KeyStore keyStore = KeyStore.getInstance("BKS");
            KeyStore trustStore = KeyStore.getInstance("BKS");
            InputStream inKey= context.getResources().openRawResource(R.raw.client);
            InputStream inTrust = context.getResources().openRawResource(R.raw.clienttruststore);
            try {
                keyStore.load(inKey, ks.toCharArray());
                trustStore.load(inTrust, ts.toCharArray());
            } finally {
                inKey.close();
                inTrust.close();
            }
            return new SSLSocketFactory(trustStore);
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

// MainActivity

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        setStrictMode();

        final HttpClient client = new SecureHttpClient(this);

        // Provide ip or address to where your test server is runnning
        final HttpGet request = new HttpGet("https://192.168.0.105:8000/");

        HttpResponse response = null;
        try {
            response = client.execute(request);
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Log.d("ExampleActivity", "Response code: " + response.getStatusLine().getStatusCode());
    }

    @TargetApi(9) 
    private void setStrictMode() {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

        StrictMode.setThreadPolicy(policy); 
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

Well, it seems your server is running on port 8000 and your Android app only register the SSLSocketFactory for 443, so it is essentially trying to speak HTTP to an HTTPS server. Either use port 443 for the server, or register for 8000 in the SchemeRegistry .

Replacing the client key+certificate bks file with a pkcs12 seems to fix the issue. I have no idea why however.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM