জাভাতে এক্স 509 সার্টিফিকেট থেকে সিএন কীভাবে উত্তোলন করবেন?


92

আমি একটি SslServerSocketএবং ক্লায়েন্ট শংসাপত্র ব্যবহার করছি এবং ক্লায়েন্টের সাবজেক্টডিএন থেকে সিএন উত্তোলন করতে চাই X509Certificate

এই মুহুর্তে আমি কল করি cert.getSubjectX500Principal().getName()তবে অবশ্যই এটি ক্লায়েন্টের মোট ফর্ম্যাট ডিএন দেয়। কিছু কারণে আমি কেবল CN=theclientডিএন এর অংশে আগ্রহী । স্ট্রিংকে নিজের বিশ্লেষণ না করে ডিএন-র এই অংশটি বের করার কোনও উপায় আছে কি?



4
@ আহমাদআবেদলঘ্নি আপনি বুঝতে পেরেছেন যে আমার প্রশ্নটি লিঙ্কযুক্তটির চেয়ে প্রায় 1.5 বছর বড়? তাই আপনি যদি কিছু, অন্যান্য খনি :-) সদৃশ
মার্টিন সি

ন্যায্য বিন্দু. আমি অন্য একটি পতাকা করব।
আহমদ আবদেলঘানি

স্ট্রিম সমাধান অভিজিৎ সরকার এখানে লিঙ্কের বর্ণনা প্রবেশ করান ঠিক আছে!
খ্রিস্টান এম

উত্তর:


90

নতুন অবহিত বাউন্সিস্টল এপিআইয়ের জন্য এখানে কিছু কোড। আপনার বিসিমেইল এবং বিসিপ্রভ উভয় বিতরণ দরকার হবে।

X509Certificate cert = ...;

X500Name x500name = new JcaX509CertificateHolder(cert).getSubject();
RDN cn = x500name.getRDNs(BCStyle.CN)[0];

return IETFUtils.valueToString(cn.getFirst().getValue());

10
@ গ্রাক, আপনি কীভাবে এই সমাধানটি বের করেছেন তাতে আমি আগ্রহী। অবশ্যই এপিআই ডকুমেন্টেশনগুলি দেখে আমি কখনই এটির সন্ধান করতে পারব না।
এলিয়ট ভার্গাস

4
হ্যাঁ, আমি সেই অনুভূতিটি শেয়ার করি ... আমাকে মেইলিং লিস্টে জিজ্ঞাসা করতে হয়েছিল।
gtrak

7
নোট করুন যে এই কোডটি বর্তমান (অক্টোবর 23 2012) বাউন্সিস্টেল (1.47) এও বিসিপিকিক্স বিতরণ প্রয়োজন।
EwyynTomato

একটি শংসাপত্রের একাধিক সিএন থাকতে পারে। কেবল cn.getFrst () ফিরিয়ে দেওয়ার পরিবর্তে আপনার উচিত সমস্ত মাধ্যমে পুনরাবৃত্তি হওয়া এবং সিএনগুলির একটি তালিকা ফিরে আসা উচিত।
ভেরুনার

4
এর দ্বারা IETFUtils.valueToStringসঠিক ফলাফল দেখা যাচ্ছে না। আমার কাছে একটি সিএন রয়েছে যাতে বেস 64 এনকোডিংয়ের (উদাহরণস্বরূপ AAECAwQFBgcICQoLDA0ODw==) কিছু সমান চিহ্ন রয়েছে । valueToStringপদ্ধতি ফলাফল স্ল্যাশ ফিরে যোগ করা হয়েছে। তার পরিবর্তে, ব্যবহার করে কাজ করা toStringবলে মনে হচ্ছে। এটি প্রকৃতপক্ষে এপিআই-র সঠিক ব্যবহার to
ক্রিস

94

এখানে অন্য উপায়। ধারণাটি হ'ল যে ডিএনএন আপনি পেয়েছেন তা rfc2253 ফর্ম্যাটে রয়েছে যা এলডিএপি ডিএন-র জন্য ব্যবহৃত হিসাবে একই। তাহলে কেন এলডিএপি এপিআই পুনরায় ব্যবহার করবেন না?

import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;

String dn = x509cert.getSubjectX500Principal().getName();
LdapName ldapDN = new LdapName(dn);
for(Rdn rdn: ldapDN.getRdns()) {
    System.out.println(rdn.getType() + " -> " + rdn.getValue());
}

4
যদি আপনি বসন্ত ব্যবহার করছেন তবে একটি দরকারী শর্টকাট: LdapUtils.getStringValue (ldapDN, "cn");
বার্থিয়ার লেমিয়াক্স

: দয়া করে আমার প্রশ্নের এ দৃষ্টিশক্তি আছে stackoverflow.com/questions/40613147/...
হোসেন Aqajani

কেস আমি সিএন কাজ করছি জন্য কমপক্ষে হয় মধ্যে একটি বহু-অ্যাট্রিবিউট RDN। অন্য কথায়: প্রস্তাবিত সমাধান আরডিএন এর গুণাবলী নিয়ে পুনরাবৃত্তি করে না। এটা করা উচিত!
পিটারহ

String commonName = new LdapName(certificate.getSubjectX500Principal().getName()).getRdns().stream() .filter(i -> i.getType().equalsIgnoreCase("CN")).findFirst().get().getValue().toString();
রেটো হেনার

দ্রষ্টব্য: যদিও এটি সূক্ষ্ম সমাধানের মতো দেখায়, এটিতে কিছু সমস্যা রয়েছে। "অ-স্ট্যান্ডার্ড" ক্ষেত্রগুলির সাথে ডিকোডিংয়ের সমস্যাগুলি আবিষ্কার না করা অবধি আমি কয়েক বছর এটি ব্যবহার করছিলাম। ক্ষেত্রের জন্য সুপরিচিত প্রকারের মতো ক্ষেত্রগুলির জন্য CN(ওরফে 2.5.4.3) Rdn#getValue()রয়েছে একটি String। তবে কাস্টম ধরণের ক্ষেত্রে ফলাফলটি byte[](সম্ভবত কোনও অভ্যন্তরীণ এনকোডযুক্ত উপস্থাপনার উপর ভিত্তি করে #)। অফসি, byte[]-> Stringসম্ভব তবে এতে অতিরিক্ত (অপ্রত্যাশিত) অক্ষর রয়েছে। আমি বিসি এর উপর ভিত্তি করে @ লাজ সমাধানগুলি সমাধান করেছি, কারণ এটি এটিকে সঠিকভাবে পরিচালনা করে এবং ডিকোড করে String
নাল্লি

12

যদি নির্ভরতা যুক্ত করা কোনও সমস্যা না হয় তবে আপনি এক্স .509 শংসাপত্রগুলির সাথে কাজ করার জন্য বাউন্সি ক্যাসলের এপিআই দিয়ে এটি করতে পারেন :

import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.jce.PrincipalUtil;
import org.bouncycastle.jce.X509Principal;

...

final X509Principal principal = PrincipalUtil.getSubjectX509Principal(cert);
final Vector<?> values = principal.getValues(X509Name.CN);
final String cn = (String) values.get(0);

হালনাগাদ

এই পোস্টিংয়ের সময়, এটি করার উপায় ছিল। মন্তব্যগুলিতে যেমন gtrak উল্লেখ করেছে, এই পদ্ধতির এখন অবচয় করা হয়েছে। Gtrak এর আপডেট হওয়া কোডটি দেখুন যা নতুন বাউন্সি ক্যাসল API ব্যবহার করে।


দেখে মনে হচ্ছে X509Name বোউনসিস্টেল ১. in46 এ অবচয় করা হয়েছে এবং তারা x500 নাম ব্যবহার করার ইচ্ছা নিয়েছে। সে সম্পর্কে কিছু জানুন বা একই জিনিসটি করার উদ্দেশ্যে করা বিকল্প?
gtrak

বাহ, নতুন এপিআইয়ের দিকে তাকিয়ে আমি উপরের কোডটির মতো একই লক্ষ্য কীভাবে অর্জন করতে পারি তা বুঝতে খুব কষ্ট পাচ্ছি। সম্ভবত বাউনিস্টেল মেলিং তালিকার সংরক্ষণাগারগুলির উত্তর থাকতে পারে। আমি এই উত্তরটি যদি বের করে নিই তবে আপডেট করব
ল্যাজ

আমারও একই সমস্যা হচ্ছে আপনি কিছু নিয়ে আসে দয়া করে আমাকে জানান। এটি যতদূর আমি পেয়েছি: x500name = X500Name.getInstance (প্রিন্সিপালUtil.getIssuerX509 প্রিন্সিপাল (সার্ট)); আরডিএন সিএন = x500name.getRDNs (বিসিএসটি.এলএন) [0];
gtrak

একটি মেইলিং তালিকা আলোচনার মাধ্যমে এটি কীভাবে করব তা আমি খুঁজে পেয়েছি, আমি একটি উত্তর তৈরি করেছি যা দেখায় যে কীভাবে।
gtrak

ভাল খুঁজে gtrak। আমি এক মুহুর্তে এটি বের করার চেষ্টা করে 10 মিনিট সময় কাটিয়েছি এবং এর আগে আর ফিরে পাইনি।
ল্যাজ

9

Gtrak কোডের বিকল্প হিসাবে যা '' বিসিমেইল '' প্রয়োজন নেই:

    X509Certificate cert = ...;
    X500Principal principal = cert.getSubjectX500Principal();

    X500Name x500name = new X500Name( principal.getName() );
    RDN cn = x500name.getRDNs(BCStyle.CN)[0]);

    return IETFUtils.valueToString(cn.getFirst().getValue());

@ জাকুব: অ্যান্ড্রয়েডে আমার এসডাব্লু চালানো না হওয়া পর্যন্ত আমি আপনার সমাধানটি ব্যবহার করেছি। এবং অ্যান্ড্রয়েড javax.naming.ldap প্রয়োগ করে না :-(


ঠিক এই কারণেই আমি এই সমাধানটির সাথে ক্যামেরা করেছি: অ্যান্ড্রয়েডে পোর্টিং ...
আইভিন

8
কখন পরিবর্তিত হয়েছে তা নিশ্চিত নয়, তবে এটি এখন কাজ করে: X500Name x500Name = new X500Name(cert.getSubjectX500Principal().getName()); String cn = x500Name.getCommonName();(জাভা 8 ব্যবহার করে)
ট্রাইচনার

: দয়া করে আমার প্রশ্নের এ দৃষ্টিশক্তি আছে stackoverflow.com/questions/40613147/...
হোসেন Aqajani

IETFUtils.valueToStringমান ফেরৎ পলান ফর্ম। .toString()পরিবর্তে আমার জন্য কাজ করার জন্য আমি কেবল অনুরোধ করতে পেলাম ।
holmis83

7

Http://www.cryptacular.org এর সাথে একটি লাইন

CertUtil.subjectCN(certificate);

জাভাডোক: http://www.cryptacular.org/javadocs/org/cryptacular/util/CertUtil.html#subjectCN(java.security.cert.X509 সার্টিফিকেট )

মাভেন নির্ভরতা:

<dependency>
    <groupId>org.cryptacular</groupId>
    <artifactId>cryptacular</artifactId>
    <version>1.1.0</version>
</dependency>

নোট করুন যে ক্রিপ্টাকুলার 1.1.x সিরিজটি জাভা 8 এবং জাভা 8 এর জন্য 1.2.x এর জন্য Very খুব ভাল গ্রন্থাগার, যদিও!
মার্কাস এল

6

এখনও অবধি পোস্ট করা সমস্ত উত্তরগুলির কিছু সমস্যা রয়েছে: বেশিরভাগ অভ্যন্তরীণ X500Nameবা বহিরাগত বাউন্টি ক্যাসল নির্ভরতা ব্যবহার করে । নিম্নলিখিতগুলি @ জাকুবের উত্তরের উপর ভিত্তি করে তৈরি করে এবং কেবলমাত্র পাবলিক জেডিকে এপিআই ব্যবহার করে, তবে ওপি-র অনুরোধ অনুযায়ী সিএনও বের করে। এটি জাভা 8ও ব্যবহার করে, যা 2017-এর মাঝামাঝি সময়ে দাঁড়িয়ে, আপনার সত্যই হওয়া উচিত।

Stream.of(certificate)
    .map(cert -> cert.getSubjectX500Principal().getName())
    .flatMap(name -> {
        try {
            return new LdapName(name).getRdns().stream()
                    .filter(rdn -> rdn.getType().equalsIgnoreCase("cn"))
                    .map(rdn -> rdn.getValue().toString());
        } catch (InvalidNameException e) {
            log.warn("Failed to get certificate CN.", e);
            return Stream.empty();
        }
    })
    .collect(joining(", "))

আমার ক্ষেত্রে সিএন হয় মধ্যে একটি বহু-অ্যাট্রিবিউট RDN। আমি মনে করি আপনাকে এই সমাধানটি বাড়িয়ে তুলতে হবে যাতে প্রতিটি আরডিএন এর জন্য আপনি আরডিএন বৈশিষ্ট্যগুলি নিয়ে পুনরাবৃত্তি করতে পারেন, বরং কেবল আরডিএন এর প্রথম বৈশিষ্ট্যটি দেখছেন, যা আমি মনে করি আপনি এখানে স্পষ্টভাবে যা করছেন।
পিটারহ

4

cert.getSubjectX500Principal().getName()আপনি যদি বাউন্সিস্টালে নির্ভরতা নিতে না চান তবে একটি রেজিটক্স ওভার ব্যবহার করে এটি কীভাবে করা যায় তা এখানে ।

এই রেজেক্স প্রতিটি ম্যাচের জন্য একটি বিশিষ্ট নাম, দেওয়া nameএবং valক্যাপচার গ্রুপকে বিশ্লেষণ করবে ।

যখন ডিএন স্ট্রিংগুলিতে কমা থাকে, তখন এগুলি উদ্ধৃত করে বোঝানো হয় - এই রেজেক্সটি উদ্ধৃত এবং উদ্ধৃত দুটি স্ট্রিং সঠিকভাবে পরিচালনা করে এবং উদ্ধৃত স্ট্রিংগুলিতে পালিয়ে যাওয়া উদ্ধৃতিগুলিও পরিচালনা করে:

(?:^|,\s?)(?:(?<name>[A-Z]+)=(?<val>"(?:[^"]|"")+"|[^,]+))+

এখানে সুন্দরভাবে ফর্ম্যাট করা হয়েছে:

(?:^|,\s?)
(?:
    (?<name>[A-Z]+)=
    (?<val>"(?:[^"]|"")+"|[^,]+)
)+

এখানে একটি লিঙ্ক রয়েছে যাতে আপনি এটি কার্যত দেখতে পারেন: https://regex101.com/r/zfZX3f/2

আপনি যদি কেবলমাত্র সিএন পেতে একটি রেজেক্স চান , তবে এই অভিযোজিত সংস্করণটি এটি করবে:

(?:^|,\s?)(?:CN=(?<val>"(?:[^"]|"")+"|[^,]+))


চারপাশে সবচেয়ে জোরালো উত্তর। এছাড়াও, আপনি যদি তার সংখ্যা (যেমন OID.2.5.4.97) দ্বারা নির্দিষ্ট OID এর সমর্থন করতে চান তবে অনুমোদিত অক্ষরগুলি [এজেড] থেকে [এজেড, 0-9%] পর্যন্ত প্রসারিত করা উচিত
ইউরিস্লাভ

3

আমার বাউন্সিস্টেল 1.49 রয়েছে এবং এটি এখন ক্লাসে org.bouncycastle.asn1.x509. সার্টিফিকেট। আমি কোডটি দেখেছি IETFUtils.valueToString()- এটি ব্যাকস্ল্যাশগুলি সহ কিছুটা অভিনব পালানোর কাজ করছে। একটি ডোমেন নামের জন্য এটি খারাপ কিছু করবে না তবে আমি অনুভব করি আমরা আরও ভাল করতে পারি। ক্ষেত্রে আমি cn.getFirst().getValue()বিভিন্ন ধরণের স্ট্রিংগুলি দেখেছি যেগুলি সমস্ত এএসএন 1 স্ট্রিং ইন্টারফেস প্রয়োগ করে, যা একটি গেটস্ট্রিং () পদ্ধতি সরবরাহ করার জন্য রয়েছে। সুতরাং, আমার জন্য কাজ করে বলে মনে হচ্ছে তা হ'ল

Certificate c = ...;
RDN cn = c.getSubject().getRDNs(BCStyle.CN)[0];
return ((ASN1String)cn.getFirst().getValue()).getString();

আমি ব্যাকস্ল্যাশ সমস্যায় পড়েছিলাম, সুতরাং এটি আমার সমস্যাটি স্থির করেছে।
অ্যাম্বার

3

আপডেট: এই শ্রেণিটি "সান" প্যাকেজে রয়েছে এবং আপনার এটিকে সতর্কতার সাথে ব্যবহার করা উচিত। মন্তব্যটির জন্য ধন্যবাদ এমিল :)

শুধু ভাগ করতে চেয়েছি, সিএন পেতে, আমি করি:

X500Name.asX500Name(cert.getSubjectX500Principal()).getCommonName();

এমিল লুন্ডবার্গের মন্তব্য সম্পর্কে দেখুন: বিকাশকারীদের কেন এমন প্রোগ্রাম লিখবেন না যেগুলি 'সান' প্যাকেজ বলে


এটি বর্তমানের উত্তরগুলির মধ্যে আমার প্রিয় কারণ এটি সাধারণ, পাঠযোগ্য এবং জেডিকে কেবল যা বান্ডিল হয়েছে তা ব্যবহার করে।
এমিল লুন্ডবার্গ

আপনি জেডি কে ক্লাস ব্যবহার সম্পর্কে যা বলেছিলেন তাতে সম্মত হন :)
র্যাড

4
তবে একটি খেয়াল করা উচিত যে জাভ্যাক X500Nameএকটি অভ্যন্তরীণ মালিকানাধীন API হওয়ার বিষয়ে সতর্ক করে যা ভবিষ্যতে প্রকাশে মুছে ফেলা হতে পারে।
এমিল লুন্ডবার্গ

হ্যাঁ, লিঙ্কযুক্ত FAQ পড়ার পরে আমার প্রথম মন্তব্যটি প্রত্যাহার করা দরকার। দুঃখিত
এমিল লুন্ডবার্গ

4
মোটেই কোন সমস্যা নেই. আপনি যা নির্দেশ করেছেন তা সত্যই গুরুত্বপূর্ণ। ধন্যবাদ :) আসলে, আমি আর এই ক্লাসটি আর ব্যবহার করি না: পি
রড

2

প্রকৃতপক্ষে, gtrakএটি ধন্যবাদ বলে মনে হয় যে ক্লায়েন্টের শংসাপত্র পেতে এবং সিএন উত্তোলন করতে, এটি সম্ভবত কার্যকরভাবে কাজ করে।

    X509Certificate[] certs = (X509Certificate[]) httpServletRequest
        .getAttribute("javax.servlet.request.X509Certificate");
    X509Certificate cert = certs[0];
    X509CertificateHolder x509CertificateHolder = new X509CertificateHolder(cert.getEncoded());
    X500Name x500Name = x509CertificateHolder.getSubject();
    RDN[] rdns = x500Name.getRDNs(BCStyle.CN);
    RDN rdn = rdns[0];
    String name = IETFUtils.valueToString(rdn.getFirst().getValue());
    return name;

এই প্রাসঙ্গিক প্রশ্নটির পরীক্ষা করুন stackoverflow.com/a/28295134/2413303
EpicPandaForce

1

ক্রিপ্টাকুলারটি সহজে ব্যবহারের জন্য বাউন্সিস্টলের উপরে জাভা ক্রিপ্টোগ্রাফিক লাইব্রেরি তৈরি করতে পারে।

RDNSequence dn = new NameReader(cert).readSubject();
return dn.getValue(StandardAttributeType.CommonName);

@ এরদেম মেমিসিয়াজিকির পরামর্শটি আরও ভাল ব্যবহার করুন।
ঘেটোলে

1

আপনি getName ব্যবহার করার চেষ্টা করতে পারেন (এক্স 500 প্রিন্সিপাল। আরএফসি 2253, ওডম্যাপ) বা কোনটিgetName(X500Principal.CANONICAL, oidMap) ডিএন স্ট্রিংকে সেরা রূপ দেয় তা দেখতে। oidMapমানচিত্রের মানগুলির মধ্যে একটি হতে পারে আপনার পছন্দ মতো স্ট্রিং।


1

শংসাপত্র থেকে সিএন আনার বিষয়টি এত সহজ নয়। নীচের কোডটি অবশ্যই আপনাকে সহায়তা করবে।

String certificateURL = "C://XYZ.cer";      //just pass location

CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate testCertificate = (X509Certificate)cf.generateCertificate(new FileInputStream(certificateURL));
String certificateName = X500Name.asX500Name((new X509CertImpl(testCertificate.getEncoded()).getSubjectX500Principal())).getCommonName();

1

সরল জাভা সহ আরও একটি উপায়:

public static String getCommonName(X509Certificate certificate) {
    String name = certificate.getSubjectX500Principal().getName();
    int start = name.indexOf("CN=");
    int end = name.indexOf(",", start);
    if (end == -1) {
        end = name.length();
    }
    return name.substring(start + 3, end);
}

0

রেজেক্স এক্সপ্রেশন, ব্যবহার করা বরং ব্যয়বহুল। এত সাধারণ কাজের জন্য এটি সম্ভবত একটি ওভার কিল হবে। পরিবর্তে আপনি একটি সাধারণ স্ট্রিং বিভক্ত ব্যবহার করতে পারেন:

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 "";
}

আমি সত্যিই এটা পছন্দ করি! প্ল্যাটফর্ম এবং গ্রন্থাগার স্বাধীন। এটা সত্যিই দুর্দান্ত!
ইউজার 2007447

4
আমার কাছ থেকে ভোট আপনি যদি আরএফসি 2253 পড়েন তবে আপনি দেখতে পাবেন যে ধারার কেসগুলি আপনাকে বিবেচনা করতে হবে, যেমন পালিয়ে যাওয়া কমা \,বা উদ্ধৃত মানগুলি।
ডানকান জোন্স

0

এক্স 500 নামটি জেডিকে অভ্যন্তরীণ প্রয়োগ, তবে আপনি প্রতিবিম্ব ব্যবহার করতে পারেন।

public String getCN(String formatedDN) throws Exception{
    Class<?> x500NameClzz = Class.forName("sun.security.x509.X500Name");
    Constructor<?> constructor = x500NameClzz.getConstructor(String.class);
    Object x500NameInst = constructor.newInstance(formatedDN);
    Method method = x500NameClzz.getMethod("getCommonName", null);
    return (String)method.invoke(x500NameInst, null);
}

0

বিসি নিষ্কাশনকে অনেক সহজ করে তুলেছিল:

X500Principal principal = x509Certificate.getSubjectX500Principal();
X500Name x500name = new X500Name(principal.getName());
String cn = x500name.getCommonName();

X500Name এ আমি কোনও .getCommonName()পদ্ধতি খুঁজে পাচ্ছি না
লাও

(@ লালাপো) আপনি কি নিশ্চিত যে আপনি আসলে ব্যবহার করছেন না sun.security.x509.X500Name- যা অন্যান্য উত্তর হিসাবে বেশ কয়েক বছর আগে উল্লিখিত ছিল অনাদৃত এবং এর উপর নির্ভর করা যায় না?
dave_thompson_085

ঠিক আছে, আমি org.bouncycastle.asn1.x500.X500Nameক্লাসের
জাভাডকের সাথে

0

বহু-মূল্যবান বৈশিষ্ট্যের জন্য - এলডিএপি এপিআই ব্যবহার করে ...

        X509Certificate testCertificate = ....

        X500Principal principal = testCertificate.getSubjectX500Principal(); // return subject DN
        String dn = null;
        if (principal != null)
        {
            String value = principal.getName(); // return String representation of DN in RFC 2253
            if (value != null && value.length() > 0)
            {
                dn = value;
            }
        }

        if (dn != null)
        {
            LdapName ldapDN = new LdapName(dn);
            for (Rdn rdn : ldapDN.getRdns())
            {
                Attributes attributes = rdn != null
                    ? rdn.toAttributes()
                    : null;

                Attribute attribute = attributes != null
                    ? attributes.get("CN")
                    : null;
                if (attribute != null)
                {
                    NamingEnumeration<?> values = attribute.getAll();
                    while (values != null && values.hasMoreElements())
                    {
                        Object o = values.next();
                        if (o != null && o instanceof String)
                        {
                            String cnValue = (String) o;
                        }
                    }
                }
            }
        }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.