So I’ve been busy

And since I have been busy I figured it would be fair to give you an insight into some of the crap I have to deal with. Here’s a past major grievance:

1) Who the hell came up the Authenticator singleton over at the JDK team? What the fuck were you smoking? Seriously? Authenticator.setDefault() is one of the DUMBEST things I have seen in a long time. Why oh why not let people attach authenticators to HttpURLConnections if they want to on a per instance basis?

2) On the topic of HttpURLConnections, who came up with the brilliant idea to make transparentNTLMlogins the default and UNCHANGEABLE. Again with the IDIOT! Come on. This is just stupid. I know you were thinking “Client” but feel free to take your head out of your ass for four seconds and think “Server” instead. One of the major issues with NTLM is the lack of delegation and in some cases that delegation is easy to solve using intermediary accounts mapped to authenticated users’ roles. OK?

Well children, you will now get to see some bonafide code. This doesn’t happen often so enjoy. If you want to bypass issue 2 above then you only have to do the following:

try{
            Field f = sun.net.www.protocol.http.HttpURLConnection.class.getDeclaredField(“tryTransparentNTLMServer”);
            f.setAccessible(true);
            f.setBoolean(urlConnection, false);
            f = sun.net.www.protocol.http.HttpURLConnection.class.getDeclaredField(“tryTransparentNTLMProxy”);
            f.setAccessible(true);
            f.setBoolean(urlConnection, false);

        } catch(NoSuchFieldException e){
            //do whatever you normally do when an error occurs, you figure it out

            e.printStackTrace();
        } catch (IllegalAccessException e) {
            //see above

            e.printStackTrace();
        }

That does the trick. No more transparent crap from that particular instance. I know that using the reflection API like that is considered bad form and that I am a BAD BAD BAD man. Fuck you. It works. I don’t care.

Now, let’s say you want to resolve issue one and you are running in a Tomcat instance: 

public class CustomAuthenticator extends Authenticator {

    HashMap<Long,PasswordAuthentication> credentials = new HashMap<Long,PasswordAuthentication>();

    public void add(String user, String pwd){

        cred.put(getThreadId(),new PasswordAuthentication(user,pwd.toCharArray()));

    }

//feel free to use some other way, like the thread name if you consider that unique, I don’t know and I don’t care
    private Long getThreadId(){
        return new Long(Thread.currentThread().getId());
    }
    private PasswordAuthentication get(Long id){
        return credentials.get(id);
    }

    protected PasswordAuthentication getPasswordAuthentication() {
        return get(getThreadId());
    }
}

Synchronize to your favorite flavor. And then set it as default using the Authenticator.setDefault()-method of craptastic hell. This works just fine with Tomcat for example. Your mileage may vary. I don’t care. Consider this an excuse for my long absence. Over and out.

(And if someone remote related to jcifs reads this… feel free to use and abuse the #1 trick if you want)


About this entry