読者です 読者をやめる 読者になる 読者になる

認証が必要なサイトへアクセスすることを考えてみた

Eclipse Plugin開発

org.eclipse.core.netとorg.eclipse.ui.netプラグインがある環境で、認証が必要なサイトへ接続すると自動でユーザ名やパスワードを入力するダイアログが表示されます。

こういうダイアログが表示されるので、ユーザ名やパスワードが必要な時に入力をうながしてくれるのはいいのですが、一度入力したのなら、どこかに情報を保持しておきたくなるわけで、どうやるのか、メモを残しておきます。

環境について

OS:Ubuntu Linux 9.10
Java:Sun Java 1.6.0-16

Javaで認証が必要なサイトに接続する仕組みをまず見てみた。

Javaには認証が必要なサイトに接続したときに認証情報を与えるための抽象クラスがあります。それがjava.net.Authenticatorです。冒頭のダイアログはEclipseが独自にAuthenticatorの具象クラスを作成して、システムに登録していた訳です。システムに登録するにはjava.net.Authenticator#setDefault(Authenticator a)というスタティックメソッドを利用します。ここで登録できるAuthenticatorはシステムでただ一つだけです。認証が必要なサイトへ接続されると、Authenticator#getPasswordAuthentication()が呼び出され、返却されるjava.net.PasswordAuthenticationを元に認証スキーマ(例えばBasic)に合わせた形で認証情報を作成して接続します。EclipseではこのAuthenticatorの具象クラス(org.eclipse.net.ui.internal.auth.NetAuthenticator)を作成し、冒頭のダイアログを表示し、ユーザ名とパスワードをユーザに入力させて認証情報を作成しています。
じゃ、このダイアログから返却されるPasswordAuthenticationをどっからか取得できれば設定を保存できる!と思って探ってみたんですが、java.net.Authenticator#getDefault()なんてメソッドは当然用意されてませんでした。次にEclipseはどうやってこのAuthenticatorを登録してるんだろう、と思って探って見ました。

Eclipseでの登録方法

Eclipseでの登録方法は、内部的な拡張ポイントorg.eclipse.core.net.authenticatorという拡張ポイントがあり、この拡張ポイントを介して登録しているのか、と思ってよくよく探っていくと、こんなコード。

class org.eclipse.core.internal.net.ProxyManager{
...
  private Authenticator getPluggedInAuthenticator() {
    IExtension[] extensions = RegistryFactory.getRegistry().getExtensionPoint(Activator.ID, Activator.PT_AUTHENTICATOR).getExtensions();
    if (extensions.length == 0)
      return null;
    IExtension extension = extensions[0];
    IConfigurationElement[] configs = extension.getConfigurationElements();
    if (configs.length == 0) {
      Activator.log(IStatus.ERROR, NLS.bind("Authenticator {0} is missing required fields", (new Object[] {extension.getUniqueIdentifier()})), null);//$NON-NLS-1$ 
      return null;
    }
    try {
      IConfigurationElement config = configs[0];
      return (Authenticator) config.createExecutableExtension("class");//$NON-NLS-1$ 
    } catch (CoreException ex) {
      Activator.log(IStatus.ERROR, NLS.bind("Unable to instantiate authenticator {0}", (new Object[] {extension.getUniqueIdentifier()})), ex);//$NON-NLS-1$ 
      return null;
    }
  }
}

最初に取得できたポイントとか。bugs.eclipse.orgを見てみても、独自に拡張してよ、みたいに書いてあるし。org.eclipse.ui.netを外して使えるようなホストごとにパスワード保存できるプラグイン作るかなぁ。