Разбор CN из сертификата DN

Позвольте мне начать с того, что это вопрос эстетики. Я решил свою проблему, мне просто интересно, как это сделать.

Итак, у меня есть DN сертификата, что-то вроде этого:

CN = Jimmy Blooptoop, OU = Someplace, OU = Сотрудники, DC = Bloopsoft-Inc

Теперь я хочу захватить CN из этого. В Java нет встроенной поддержки для захвата всего, кроме полного DN из сертификата X509, без использования какой-либо сторонней библиотеки, такой как bouncy castle – которую я не могу использовать. Поэтому я должен разобрать его, что не так много проблем. Единственное, что делает его несколько сложным, это тот факт, что CN не всегда будет отформатирован как . Чаще всего это будет , . Итак, в приведенном выше примере CN может быть Джимми Блуптотоп или Блуптооп, Джимми Дж (конечно, для Joop).

После просмотра и регулярного выражения я написал следующее, которое работает достаточно хорошо:

 Matcher m = Pattern.compile("CN=[A-Za-z]*[, ]*[ A-Za-z]*").matcher(dn); if (m.find()) cn = m.group(); 

Мне просто любопытно, есть ли выражения, которые выглядели бы менее похоже на дерьмо. Я довольно уверен, что с тех пор я работал над этим после прочтения только введения в регулярное выражение.

Как насчет javax.naming.ldap.LdapName ?

 String dn = "CN=Jimmy Blooptoop,OU=Someplace,OU=Employees,DC=Bloopsoft-Inc"; LdapName ln = new LdapName(dn); for(Rdn rdn : ln.getRdns()) { if(rdn.getType().equalsIgnoreCase("CN")) { System.err.println("CN is: " + rdn.getValue()); break; } } 

Это не самый красивый интерфейс, поскольку есть что-то отсутствует, например LdapName#getByType(String) но это избавляет вас от необходимости думать о том, какие странные функции могут иметь DN.

Вы можете избежать использования выражения ‘crappy’. Если у вас уже есть DN, вы можете разделить String, а затем найти CN. Например:

 String dn = "CN=Jimmy Blooptoop,OU=Someplace,OU=Employees,DC=Bloopsoft-Inc"; String[] split = dn.split(","); for (String x : split) { if (x.contains("CN=")) { System.out.println(x.trim()); } } 

Если вы используете Spring Framework, вы можете использовать DistinguishedName следующим образом:

 String path = "CN=Jimmy Blooptoop,OU=Someplace,OU=Employees,DC=Bloopsoft-Inc"; DistinguishedName dn = new DistinguishedName(path); String cn = dn.getValue("cn"); // Jimmy Blooptoop 

Вы можете использовать Spring Frameworks LdapUtils для извлечения CN в аккуратном виде, как LdapUtils ниже:

 String cn = LdapUtils.getStringValue(new LdapName(group),"cn"); 

ИЛИ

Без использования Spring Framework, как показано ниже:

 String cn = (String)new LdapName(group).getRdns().stream().filter(rdn -> rdn.getType().equalsIgnoreCase("CN")).findFirst().get().getValue(); 

Вы не должны использовать регулярные выражения, предложенные выше. Проблема с этими регулярными выражениями заключается в том, что вы не будете следовать RFC 4514 и не будете игнорировать ранее экранированные символы и могут потенциально потерять или неправильно интерпретировать выдающееся имя. Вместо этого используйте class LdapName, как рекомендовано musiKk, для правильного анализа отличительного имени.

Regex, довольно дороги в использовании. Для такой простой задачи это, вероятно, будет больше, чем убийство. Вместо этого вы можете использовать простое разделение строк:

 String dn = ((X509Certificate) certificate).getIssuerDN().getName(); String CN = getValByAttributeTypeFromIssuerDN(dn,"CN="); private String getValByAttributeTypeFromIssuerDN(String dn, String attributeType) { String[] dnSplits = dn.split(","); for (String dnSplit : dnSplits) { if (dnSplit.contains(attributeType)) { String[] cnSplits = dnSplit.trim().split("="); if(cnSplits[1]!= null) { return cnSplits[1].trim(); } } } return ""; } 

Похоже, это работает нормально

 CertificateFactory fact = CertificateFactory.getInstance("X.509"); FileInputStream is = new FileInputStream ("cert.pem"); X509Certificate cert = (X509Certificate) fact.generateCertificate(is); String cn = ((X500Name)cert.getSubjectDN()).getCommonName() 

Если я правильно понял, это должно привести к тому же результату, просто выглядит немного более читаемым. \w соответствует любому символу слова.

 "CN=[\\w]*[., ]+[\\w ]*" 

Если вы хотите что-то более гибкое, вы можете сделать это:

 Matcher m = Pattern.compile("(CN=.*?),[AZ]{2}=").matcher(dn); if (m.find()) cn = m.group(1); 

Это соответствует чему-либо между «CN =» и «, XX =», где XX – две заглавные буквы. group(1) возвращает первую группу (совпадение внутри круглых скобок).

Regexp не так сложно, как они выглядят!

Я разбираю DN как это. Вы получаете все атрибуты как свойства:

 Principal principal = cert.getSubjectDN(); Properties prop = new Properties(); prop.load(new StringReader(principal.getName().replaceAll(",", "\n"))); prop.list(System.out); String CN= props.get("CN"); 

Однако он не работает для повторяющихся элементов, таких как ou или dc.

  • Regex для строки с кавычками
  • Regex найти целые слова
  • Удаление пустых строк в Notepad ++
  • Регулярное выражение для сопоставления URL-адресов в Java
  • Как извлечь подстроку с помощью регулярного выражения
  • Как удалить все не буквенно-цифровые символы из строки, кроме тире?
  • Ошибка RE: незаконная последовательность байтов в Mac OS X
  • Возможно ли, чтобы компьютер «научил» регулярное выражение примерами, предоставленными пользователем?
  • Регулярное выражение для пароля должно содержать не менее восьми символов, как минимум одно число и буквы нижнего и верхнего регистра и специальные символы
  • Как сопоставить строку в круглых скобках (вложенных) в Java?
  • Создать массив совпадений регулярных выражений
  • Interesting Posts

    Связывание ASP.NET – пакет, не обновляющийся после того, как включен файл с добавлением (возвращается 304 не изменен)

    В Windows 7 как отключить прокрутку панели инструментов?

    Как переименовать некоторые файлы в соответствии с их меткой времени

    Как сделать углы кнопки круглыми?

    Как определить, принадлежит ли точка определенной строке?

    Как выполнить rsync большой файл с минимальными затратами на процессор и пропускную способность?

    Ls -la symbolics … что означает этот последний символ?

    Что такое интерфейс IUserSecurityStampStore ASP.NET Identity?

    Что такое NSCFDictionary?

    Хорошие примеры не functor / functor / Applicative / Monad?

    Как обновить или перезагрузить Windows 8 без раздела System Reserved?

    Android JDBC не работает: ClassNotFoundException на драйвере

    Как открыть второе окно из первого windows в WPF?

    Можете ли вы пройти по ссылке в R?

    Django: разрешение отклонено при попытке доступа к базе данных после восстановления (миграции)

    Давайте будем гением компьютера.