Android Windows authentication

后端 未结 2 1085
南旧
南旧 2021-01-28 13:38

DefaultHttpHandler is deprecated, HttpURLConnection does not support NTLM and NTLM seems to be the only well-supported protocol by ASP.NET MCV websites. So, what\'s left to do?<

相关标签:
2条回答
  • 2021-01-28 14:14

    Okay so the first thing I did was to import the JCIFS library. Its a jar you download from that link.

    The next thing I needed to do was to import the JCIFSEngine class and NTLMSchemeFactory class into your project.

    Then finally this method builds your HTTPClient:

    //I know it is deprecated but there is no other way to implement NTLM thus far.
        private static DefaultHttpClient setupHttpClient (String username, String password) {
            DefaultHttpClient httpclient = new DefaultHttpClient();
            // register ntlm auth scheme
            httpclient.getAuthSchemes().register("ntlm", new NTLMSchemeFactory());
            httpclient.getCredentialsProvider().setCredentials(
                    // Limit the credentials only to the specified domain and port
                    new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
                    // Specify credentials, most of the time only user/pass is needed
                    new NTCredentials(username, password, "", "")
            );
            return httpclient;
        }
    

    My connections are done with Retrofit so I just attach this HTTPClient to retrofit using the following line:

    retrofitAdapterBuilder.setClient(new ApacheClient(setupHttpClient(username, password)));
    

    This worked for me thus far even-though it is really bad that Android has no native support for this.

    EDIT: Adding an Okhttp implementation. This is an old class and we are no longer using it as we decided to drop NTLM support, but it used to work. Please keep in mind that we connect to servers that can have basic/windows/azure authentication so we need to do multiple checks which you might not need to do.

    First create a class which implements the Authenticator interface from okhttp. Then in the authenticate() method do the following:

        @Override
    public Request authenticate(Route route, okhttp3.Response response) throws IOException {
        if (response == null || response.headers() == null || response.headers().toString().isEmpty()) {
            return null;
        }
    
        final List<String> authHeaders = response.headers().values("WWW-Authenticate");
    
        if (authHeaders.contains("NTLM")) {
            return response.request().newBuilder().header("Authorization", "NTLM " + mNtlmInitialChallenge).build();
        } else if (checkIsBasicAuth(authHeaders)) {
            String credentials = mUsername + ":" + mPassword;
            final String basic = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
            return response.request().newBuilder().header("Authorization", basic).build();
        }
    
        if (mChallengeSent) {
            return null;
        } else {
            mChallengeSent = true;
            String ntlmFinalChallenge = null;
            try {
                ntlmFinalChallenge = mNtlmEngine.generateType3Msg(mUsername, mPassword, mDomain, "android-device", authHeaders.get(0).substring(5));
            } catch (Exception e) {
                e.printStackTrace();
            }
            return response.request().newBuilder().header("Authorization", "NTLM " + ntlmFinalChallenge).build();
        }
    }
    

    To generate the mNtlmInitialChallenge create the following method:

        private String getInitialNtlmChallenge() {
        String initialChallenge = null;
        try {
            initialChallenge = mNtlmEngine.generateType1Msg(null, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    
        return initialChallenge;
    }
    

    The mNtlmEngine class I copied over from the JCIFS library manually so I could remove the dependency.

    Some notes:

    1. The code is not the cleanest as this was a POC.

    2. Yes we used the dreaded mVariable notation, we are not using it anymore.

    3. You are going to have to play around with this implementation until it works for you.

    4. To attach the authenticator to okhttp just do client.authenticator(new NtlmAuthenticator(username, password, ""));

    5. You are probably going to need to implement some failure mechanism.

    0 讨论(0)
  • 2021-01-28 14:31

    Just do FBA in MCV https://msdn.microsoft.com/en-us/library/ff398049(v=vs.100).aspx

    It is well supported.

    0 讨论(0)
提交回复
热议问题