Статьи

Объяснение аутентификации JGit

Аутентификация в JGit в основном на уровне родного Git. Поддерживаются обычно используемые протоколы, такие как SSH и HTTP (S), и методы их аутентификации. В этой статье описывается, как использовать API аутентификации JGit для безопасного доступа к удаленным репозиториям Git.

Хотя примеры в этой статье используют CloneCommand, описанные методы могут применяться ко всем классам, которые подключаются к удаленным репозиториям, таким как FetchCommand, PushCommand, LsRemoteCommand и т. Д. Все эти команды имеют общий базовый класс — TransportCommand — который предлагает обсуждаемые методы Вот.

HTTP (S) — https://example.com/repo.git

Аутентификация через HTTP и HTTPS проста. Реализация CredentialsProvider используется для возврата учетных данных аутентификации, когда команда запрашивает их. CredentialsProvider, который будет использоваться для определенной команды, может быть указан через setCredentialsProvider ().

Например, приведенный ниже код клонирует хранилище по HTTPS и аутентифицируется с помощью имени пользователя и пароля.

1
2
3
CloneCommand cloneCommand = Git.cloneRepository();
cloneCommand.setURI( "https://example.com/repo.git" );
cloneCommand.setCredentialsProvider( new UsernamePasswordCredentialsProvider( "user", "password" ) );

Имя пользователяPasswordCredentialsProvider является реализацией CredentialsProvider, которая поставляется с JGit и использует заданные имя пользователя и пароль для аутентификации.

Кроме того, JGit (версия 3.5 и выше) также может считывать учетные данные из файла .netrc пользователя. NetRCCredentialsProvider использует первую запись компьютера из файла для аутентификации.

Хотя не рекомендуется отправлять учетные данные по незащищенным соединениям, описанный подход также работает для простого HTTP, например http://example.com/repo.git.

SSH с открытым ключом — ssh: //user@example.com/repo.git

JGit делегирует создание и уничтожение SSH-соединений с абстрактным SshSessionFactory. Чтобы использовать аутентификацию с открытым ключом для соединения SSH, такая фабрика сеансов должна быть указана для выполненной команды.

С помощью setTransportConfigCallback () можно указать интерфейс TransportConfigCallback для перехвата процесса подключения. Его единственный метод с именем configure () вызывается непосредственно перед установлением соединения. Передается параметр типа Transport, который будет использоваться для копирования объектов между локальным и удаленным хранилищем. Для каждого протокола существует отдельный подкласс транспорта, который обрабатывает соответствующие детали этого протокола.

Как показано ниже, обратный вызов может использоваться для настройки экземпляра Transport непосредственно перед его использованием:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
  @Override
  protected void configure( Host host, Session session ) {
    // do nothing
  }
};
CloneCommand cloneCommand = Git.cloneRepository();
cloneCommand.setURI( "ssh://user@example.com/repo.git" );
cloneCommand.setTransportConfigCallback( new TransportConfigCallback() {
  @Override
  public void configure( Transport transport ) {
    SshTransport sshTransport = ( SshTransport )transport;
    sshTransport.setSshSessionFactory( sshSessionFactory );
  }
} );

JGit предоставляет абстрактный JSchConfigSessionFactory, который использует JSch для установки SSH-соединений и требует переопределения его configure (). Поскольку в простейшем случае не нужно ничего настраивать, приведенный выше пример просто переопределяет метод, позволяющий компилировать код.

JSchConfigSessionFactory в основном совместим с OpenSSH, реализацией SSH, используемой нативным Git. Он загружает известные хосты и закрытые ключи из их местоположений по умолчанию (identity, id_rsa и id_dsa) в пользовательский каталог .ssh.

Если ваш файл закрытого ключа назван по-другому или находится в другом месте, я рекомендую переопределить createDefaultJSch (). После вызова базового метода можно добавить собственные закрытые ключи следующим образом:

1
2
3
4
5
6
@Override
protected JSch createDefaultJSch( FS fs ) throws JSchException {
  JSch defaultJSch = super.createDefaultJSch( fs );
  defaultJSch.addIdentity( "/path/to/private_key" )
  return defaultJSch;
}

В этом примере добавлен закрытый ключ из пользовательского местоположения файла. Если вы загляните в JSch JavaDoc, вы найдете другие перегруженные методы addIdentity ().

Для полноты картины следует отметить, что существует также глобальная фабрика сессий. Его можно получить и изменить с помощью SshSessionFactory.get / setInstance () и использовать по умолчанию, если для команды не был настроен конкретный shSessionFactory. Тем не менее, я рекомендую воздержаться от его использования. Помимо усложнения написания изолированных тестов, может существовать код вне вашего контроля, который изменяет глобальную фабрику сеансов.

SSH с паролем — ssh: //user@example.com/repo.git

Как и в случае использования SSH с открытыми ключами, необходимо указать SshSessionFactory для использования защищенных паролем соединений SSH. Но на этот раз у метода configure () фабрики сеансов есть цель.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
  @Override
  protected void configure( Host host, Session session ) {
    session.setPassword( "password" );
  }
} );
 
CloneCommand cloneCommand = Git.cloneRepository();
cloneCommand.setURI( "ssh://user@example.com/repo.git" );
cloneCommand.setTransportConfigCallback( new TransportConfigCallback() {
  @Override
  public void configure( Transport transport ) {
    SshTransport sshTransport = ( SshTransport )transport;
    sshTransport.setSshSessionFactory( sshSessionFactory );
  }
} );

Сеанс JSch представляет соединение с сервером SSH, и в строке 4 устанавливается пароль для текущего сеанса. Остальная часть кода такая же, как и при подключении через SSH с аутентификацией с открытым ключом.

Какой метод аутентификации использовать?

Некоторые методы аутентификации, обсуждаемые здесь, также могут быть объединены. Например, установка поставщика учетных данных при попытке подключиться к удаленному хранилищу через SSH с открытым ключом не повредит. Однако обычно вы заранее хотите узнать, какой транспорт будет использоваться для заданного URL-адреса хранилища.

Чтобы определить это, можно использовать метод canHandle () TransportProtocol. Он возвращает true, если протокол может обрабатывать данный URL, и false в противном случае. Список всех зарегистрированных TransportProtocols можно получить из Transport.getTransportProtocols (). И как только протокол известен, можно выбрать подходящий метод аутентификации.

Аутентификация @ GitHub

GitHub поддерживает множество протоколов и методов аутентификации, но, конечно, не все возможные комбинации. Например, распространенной ошибкой является попытка использовать SSH с аутентификацией по паролю. Но эта комбинация не поддерживается — только SSH с открытыми ключами.

Это сравнение протоколов, предлагаемых GitHub, показывает, что поддерживается, а что нет. Обобщая, есть:

  • Простой Git (например, git: //github.com/user/repo.git): передача не зашифрована, а сервер не проверен.
  • HTTPS (например, https://github.com/user/repo.git): работает практически везде. Использует аутентификацию по паролю для отправки, но разрешает анонимную выборку и клонирование.
  • SSH (например, ssh: //git@github.com: user / repo.git): использует аутентификацию с открытым ключом, также для извлечения и клонирования.

Завершение аутентификации JGit

Хотя я нахожу, что средства аутентификации немного разбросаны по JGit API, они выполняют задачу. Надеемся, что приведенные здесь рецепты предоставят вам необходимые основы для аутентификации соединений в JGit, а сокрытие сложностей API можно рассматривать как упражнение для практики чистого кода!

Если у вас возникли трудности или вопросы, не стесняйтесь оставлять комментарии или просить дружелюбное и полезное сообщество JGit о помощи.