当前位置: 首页 > ActiveMQ in Action 读书笔记 > 正文

6.4 基于证书的安全授权机制- Certificate -based security

 6.4 Certificate-based security

Earlier in this chapter, we described ActiveMQ plug-ins used to secure the broker byauthenticating the clients and authorizing the access to destinations. These plug-insdo their work properly, but they store client credentials using plain user names andpasswords. Though this is sufficient for most users and use cases, some organizationsprefer to implement security using SSL certificates. We’ve already discussed the SSLtransport and how it uses certificates in chapter 4. In this section we’ll expand on thatmaterial and show you how the SSL transport (along with supporting plug-in) can beused to secure the broker. We’ll see how we can authenticate clients using theircertificates, but also how we can give those clients different access rights based on thecertificate they use to connect to the broker.

 6.4 基于证书的安全授权机制

本章前面部分,我们讨论了使用ActiveMQ插件,通过客户端认证并授权客户端访问消息目的地的方式来保证代理的安全.这些插件可以正常的工作,但是他们使用明文来存储客户端的用户名和密码等身份信息.对于大多数用户和大部分场景来说,这种方式已经足够使用,但是一些组织倾向于使用SSL证书来保证安全.第4章中,我们已经讨论过SSL传输连接器以及如何使用证书.本节中,我们将探讨展开对证书的讨论并且告诉你如何使用SSL传输连接器(同时支持插件)来保证代理安全.我们将看到如何使用证书认证客户端,同时看到如何根据他们借以连接到代理的证书来分配不同的访问控制权限.

 For the example in this section we’ll use our stock portfolio publisher and consumer.Just this time, they’ll use different certificates which will identify them and givethem access to publish and consume from broker destinations.  本节中我们井继续使用stock portfolio例子中的publisher和consumer,但是这次他们将分别使用不同的证书以便表名身份以及获取发布和消费代理中消息目的地消息的访问权限.

 6.4.1 Preparing certificates

Let’s start by creating appropriate certificates. The procedure here is similar to theone we used in chapter 4 for the basic SSL transport setup. We’ve provided all thesecertificates in the examples that comes with the book, so you can use them to run theexample.

 6.4.1 准备证书

下面让我从创建证书开始.创建证书的过程和第4长配置基本的SSL传输连接器类似.本书附带的示例代码中包含了所有的证书,因此你可以在本例中使用.

 We’ll create two certificates: one named producer and contained in the myproducer.ks keystore:  我们将创建2个证书,一个名称为producer存储于文件名为myproducer.ks的keystore中.创建证书命令如下:
$ keytool -genkey -alias producer -keyalg RSA -keystore myproducer.ks
Enter keystore password: test123
Re-enter new password: test123
What is your first and last name? [Unknown]: producer
What is the name of your organizational unit? [Unknown]:
Chapter 6
What is the name of your organization? [Unknown]: ActiveMQ in Action
What is the name of your City or Locality? [Unknown]: Belgrade
What is the name of your State or Province? [Unknown]:
What is the two-letter country filename for this unit? [Unknown]: RS
Is CN=producer, OU=Chapter 6, O=ActiveMQ in Action,
L=Belgrade, ST=Unknown, C=RS correct? [no]: yes
Enter key password for <producer> (RETURN if same as keystore password):
 and another called consumer and stored in the myconsumer.ks keystore:  另外还需要创建一个名称为consumer并存储在文件名为myconsumer.ks的keystore中.创建证书命令如下:
$ keytool -genkey -alias consumer -keyalg RSA -keystore myconsumer.ks
Enter keystore password: test123
What is your first and last name? [Unknown]: consumer
What is the name of your organizational unit? [Unknown]: Chapter 6
What is the name of your organization? [Unknown]: ActiveMQ in Action
What is the name of your City or Locality? [Unknown]: Belgrade
What is the name of your State or Province? [Unknown]:
What is the two-letter country code for this unit? [Unknown]: RS
Is CN=consumer, OU=Chapter 6, O=ActiveMQ in Action,
L=Belgrade, ST=Unknown, C=RS correct? [no]: yes
Enter key password for <client> (RETURN if same as keystore password):
 Note the info of the certificates we create, as we’ll use it to grant or deny access to thebroker later. Of course, in production environments you should consider keeping certificatesin secure locations to provide better security of the whole system.  注意我们创建证书时的信息,因为稍后我们将使用这些信息来授权或决绝对代理的访问.当然,在生产环境中,你应该考虑将证书存储在一个安全的位置以便为整个系统提供更好的安全保护.

 6.4.2 Creating a truststore

The next thing we need to do is import these certificates into the broker’s truststore.But first we need to export them from their keystores. Use the following command toexport the producer keystore:

 6.4.2 创建一个truststore

下一步要做的就是将上面创建的证书导入到代理的truststore(受信证书仓库)中.首先,需要将证书从keystores(证书仓库)中导出.使用下面的命令可以从producer keystore中导出证书:

$ keytool -export -alias producer -keystore myproducer.ks -file producer_cert
 
Enter keystore password: test123
Certificate stored in file <producer_cert>
 as well as the following command to export the consumer keystore:  使用下面的命令可以从consumer keystore中导出证书:
$ keytool -export -alias consumer -keystore myconsumer.ks -file consumer_cert
Enter keystore password: test123
Certificate stored in file <consumer_cert>

 Now that the JMS client certificates have been exported, the broker truststore must becreated.Creating a broker truststore and importing producer and consumer certificates isa rather straightforward task. First import the producer certificate into the brokertruststore:

 导出JMS客户端证书以后,需要创建代理的truststore(受信证书仓库).创建truststore并导入producer和consumer证书这个任务相当简单.首先,使用下面命令导入producer证书到代理的truststore:

$ keytool -import -alias producer -keystore mybroker.ts -file producer_cert
Enter keystore password:
Re-enter new password:
Owner: CN=producer, OU=Chapter 6, O=ActiveMQ in Action,
L=Belgrade, ST=Unknown, C=RS Issuer: CN=producer, OU=Chapter 6,
O=ActiveMQ in Action, L=Belgrade, ST=Unknown, C=RS
Serial number: 4b6f0cf0
Valid from: Sun Feb 07 19:56:48 CET 2010 until: Sat May 08
20:56:48 CEST 2010
Certificate fingerprints: MD5:
9A:8C:02:17:0D:B1:11:CB:4E:14:63:37:03:F3:31:AD SHA1:
21:3B:A8:15:B8:67:39:28:9C:1B:23:35:E9:9F:30:2C:4C:8D:16:85 Signature
algorithm name: SHA1withRSA Version: 3
Trust this certificate? [no]: yes
Certificate was added to keystore
 Then import the consumer certificate into the broker truststore:  接下来,使用下面的命令导入consumer证书到代理的truststore中:
$ keytool -import -alias consumer -keystore mybroker.ts -file consumer_cert
Enter keystore password:
Owner: CN=consumer, OU=Chapter 6, O=ActiveMQ in Action,
L=Belgrade, ST=Unknown, C=RS Issuer: CN=consumer, OU=Chapter 6,
O=ActiveMQ in Action, L=Belgrade, ST=Unknown, C=RS
Serial number: 4b6f0ed4
Valid from: Sun Feb 07 20:04:52 CET 2010 until: Sat May 08
21:04:52 CEST 2010 Certificate fingerprints: MD5:
6D:C9:AF:3C:AB:1D:E3:8A:C1:5D:70:71:DE:17:CE:95 SHA1:
73:F6:7B:E9:42:5C:90:EB:6F:4F:8C:CB:9E:DB:59:66:B0:EF:02:2E Signature
algorithm name: SHA1withRSA Version: 3
Trust this certificate? [no]:yes
Certificate was added to keystore
 After the broker truststore is ready, we need to place it somewhere where we can referenceit from the configuration file. This is usually the ${ACTIVEMQ_HOME}/conf/folder, where all other configuration resources reside. We’ve provided this truststorewith the examples, so all you have to do is to copy it to the right place:  处理好代理的truststore后,我们需要将truststore放到配置文件可访问的地方.通常将证书放到${ACTIVEMQ_HOME}/conf/文件夹中,所有和配置有关的文件都存放在该文件夹里.在本节的例子中我们将使用上面处理过的truststore,所以你需要做的只是将truststore拷贝到配置文件所在的目录,使用下面的命令完成拷贝:
$ cp src/main/resources/org/apache/activemq/book/ch6/mybroker.ts ${ACTIVEMQ_HOME}/conf/
 Now let’s focus on the configuration file and how we can use this truststore to configureActiveMQ security.  现在,让我们把目光集中到配置文件上面,看看我们如何利用truststore来配置ActiveMQ安全代理.

 6.4.3 Configuring the broker

The XML configuration file shown in the following listing uses the provided truststoreto instruct the SSL transport which clients are allowed to connect to the broker, andthen uses jaasCertificateAuthenticationPlugin (shown in bold) to authorizetheir access to broker resources.

Listing 6.7 Configuring certificate-based security

 6.4.3 配置代理

下面的配置的代码中使用上面提供的truststore可配置SSL传输连接器,设置哪些客户端可以连接到代理以及使用jaasCertificateAuthenticationPlugin(粗体显示)来控制客户端可以访问哪些代理上的资源.

清单6.7 基于证书的安全配置

...
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.base}/data">
  <plugins>
    <jaasCertificateAuthenticationPlugin configuration="activemq-certificate" />
    
    <authorizationPlugin>
      <map>
        <authorizationMap>
          <authorizationEntries>
            <authorizationEntry topic=">" read="admins" write="admins" admin="admins" />
            <authorizationEntry topic="STOCKS.>" read="consumers" write="publishers" admin="publishers" />
            <authorizationEntry topic="STOCKS.ORCL" read="guests" />
            <authorizationEntry topic="ActiveMQ.Advisory.>" read="admins,publishers,consumers,guests" 
                                write="admins,publishers,consumers,guests" admin="admins,publishers,consumers,guests" />
          </authorizationEntries>
        </authorizationMap>
      </map>
    </authorizationPlugin>
  </plugins>
  
  <sslContext>
    <sslContext keyStore="file:${activemq.base}/conf/mybroker.ks" 
                keyStorePassword="test123" 
                trustStore="file:${activemq.base}/conf/mybroker.ts" 
                trustStorePassword="test123"/>
  </sslContext>
  
  <transportConnectors>
    <transportConnector name="openwire" uri="tcp://localhost:61616"/>
    <transportConnector name="ssl" uri="ssl://localhost:61617?needClientAuth=true" />
  </transportConnectors>
</broker>
...
 A few things are worth noting in this configuration file, as shown in bold. First of all,we added the trustStore and trustStorePassword properties to the <sslContext>configuration, which allows us to use our previously defined broker truststore. Next,we set the needClientAuth parameter in the SSL transport URI, which instructs thebroker to check connecting client certificates and allow access only to those that arefound in the truststore.  上面配置文件中值得关注的地方使用粗体标示出来了.首先,<sslContext>中配置了trustStore和trustStorePassword属性,这两个属性允许使用我们前面定义的代理的truststore.其次,SSL的传输连接器配置URI中设置了needClientAuth值为true,这样代理要求正在连接的客户端需要提供证书,只有客户端提供证书在服务器的truststore中时,该客户端才被允许连接.

 6.4.4 Authorization explained

Now that we’ve covered authentication with certificates, it’s time to take care of authorization,and that’s why we use jaasCertificateAuthenticationPlugin. This plug-inis similar to the JAAS plug-in we used earlier in this chapter. We now configure it to lookat activemq-certificate configuration in login.config, which should look like this:

 6.4.4 授权过程解释

至此我们使用证书完成了认证配置.接下来需要关注授权,因此我们使用了jaasCertificateAuthenticationPlugin插件.改插件与本章之前使用的JAAS插件类似.现在配置jaasCertificateAuthenticationPlugin插件关联login.config文件中的activemq-certificate条目,这个条目配置代码如下所示:

activemq-certificate 
{
  org.apache.activemq.jaas.TextFileCertificateLoginModule  required debug=true
  org.apache.activemq.jaas.textfiledn.user="users.properties"
  org.apache.activemq.jaas.textfiledn.group="groups.properties";
};
 The login.config file is now different in that it uses TextFileCertificateLoginModuleinstead of PropertiesLoginModule, configured using the appropriate properties.Now it’s time to see what the user.properties file looks like:  使用TextFileCertificateLoginModule插件后,login.config文件于之前使用PropertiesLoginModule插件是有所不同,login.config中已经配置了恰当的properties文件.下面看看user.properties文件内容:
admin=password
publisher=password
consumer=password
guest=password
sslconsumer=CN=consumer, OU=Chapter 6, O=ActiveMQ in Action, L=Belgrade,ST=Unknown, C=RS
sslpublisher=CN=producer, OU=Chapter 6,O=ActiveMQ in Action, L=Belgrade, ST=Unknown, C=RS
 As you can see, we added our two certificates as sslconsumer and sslpublisher users.You may notice that the user.properties file is the place where you map your certificateto a certain username, and we used the appropriate info of the certificate to mapit to the desired username. Now that we have a username, we can put it in the certaingroup using groups.properties file:  正如你看到的,我们添加了两个证书用户sslconsumer和sslpublisher.你可能已经注意到了,在user.properties文件中你可以将证书映射到指定的用户名上– 将证书中的一些信息映射到指定的用户名.当映射成用户名后,就可以将永远吗配置到groups.properties文件中,如下所示:
admins=admin
publishers=admin,publisher,sslpublisher
consumers=admin,publisher,consumer,sslconsumer
guests=guest
 Once we have our users in their groups, the authorizationPlugin kicks in and authorizesthe access to broker’s destinations.  配置好了群组包含的用户之后,授权插件开始起作用并对代理中消息目的地的访问进行授权.

 6.4.5 Testing it out

Now let’s start the broker using the configuration and login.config file from earlier:

 6.4.5 测试

现在,可以使用前面配置和login.config文件,使用下面的命令启动代理:

${ACTIVEMQ_HOME}/bin/activemq console -Djava.security.auth.login.config=src/main/resources/org/apache/activemq/book/ch6/login.config xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-ssl.xml
(windows 命令%ACTIVEMQ_HOME%/bin/activemq -Djava.security.auth.login.config=src/main/resources/org/apache/activemq/book/ch6/login.config xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-ssl.xml)
... 
Loading message broker from:xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-ssl.xml
...
00:15:26,144 | INFO | PListStore:/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/tmp_storage started
00:15:26,312 | INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/KahaDB]
00:15:26,387 | INFO | JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
00:15:26,882 | INFO | KahaDB is version 2
00:15:26,905 | INFO | ActiveMQ 5.4.1 JMS Message Broker (localhost) isstarting
00:15:26,906 | INFO | For help or more information please see:http://activemq.apache.org/
00:15:27,044 | INFO | Scheduler using directory:/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler
00:15:27,086 | INFO | JobSchedulerStore:/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler started
00:15:27,113 | INFO | Listening for connections at: tcp://localhost:61616
00:15:27,114 | INFO | Connector openwire Started
00:15:27,810 | INFO | Listening for connections at:ssl://localhost:61617?needClientAuth=true
00:15:27,811 | INFO | Connector ssl Started
00:15:27,820 | INFO | ActiveMQ JMS Message Broker(localhost, ID:mongoose.local-51704-1289978126925-0:0) started
...
 The broker is ready, so let’s now see how clients behave depending on which certificatethey use. For example, if we try to access the broker with the original certificateused in chapter 4, we can expect that access will be denied, as that certificate isn’t inthe broker’s truststore.  代理准备就行,接下来可以看看使用不同证书的客户端的访问代理会出现什么情况.比如,如果我们使用第4章中的证书访问代理,你会发现访问会被拒绝,因为证书不在代理的truststore(受信证书库)中.
$ mvn -Djavax.net.ssl.keyStore=src/main/resources/org/apache/activemq/book/ch4/myclient.ks \
-Djavax.net.ssl.keyStorePassword=test123 \
-Djavax.net.ssl.trustStore=${ACTIVEMQ_HOME}/conf/myclient.ts \
-Djavax.net.ssl.trustStorePassword=test123 exec:java \
-Dexec.mainClass=org.apache.activemq.book.ch4.Publisher \
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
 
(window dos 命令为:
mvn -Djavax.net.ssl.keyStore=src/main/resources/org/apache/activemq/book/ch4/myclient.ks ^
-Djavax.net.ssl.keyStorePassword=test123 ^
-Djavax.net.ssl.trustStore=%ACTIVEMQ_HOME%/conf/myclient.ts ^
-Djavax.net.ssl.trustStorePassword=test123 exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher ^
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
)
...
No user for client certificate: CN=Dejan Bosanac,
OU=Chapter 4, O=ActiveMQ in Action, L=Belgrade, ST=Unknown,
C=RS
...
 Note that we’re using the client truststore from the original SSL example here, sincenothing has changed regarding certificates on the broker side.Now let’s start it with the appropriate certificate and see how it works:  注意到,我们是我们使用了前面SSL例子中客户端的truststore,因为代理端的证书没有变.现在让我使用正确的证书启动Publisher:
$ mvn -Djavax.net.ssl.keyStore=\
src/main/resources/org/apache/activemq/book/ch6/myproducer.ks \
-Djavax.net.ssl.keyStorePassword=test123 \
-Djavax.net.ssl.trustStore=${ACTIVEMQ_HOME}/conf/myclient.ts \
-Djavax.net.ssl.trustStorePassword=test123 exec:java \
-Dexec.mainClass=org.apache.activemq.book.ch4.Publisher \
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
 
(译注:window dos命令:
mvn -Djavax.net.ssl.keyStore=src/main/resources/org/apache/activemq/book/ch6/myproducer.ks ^
-Djavax.net.ssl.keyStorePassword=test123 -Djavax.net.ssl.trustStore=src/main/resources/org/apache/activemq/book/ch6/myclient.ts ^
-Djavax.net.ssl.trustStorePassword=test123 exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher ^
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
 
另,源文件中的证书都已经过期失效,需要自己创建新的证书.
)
...
Sending: {price=22.67337141688392, stock=ORCL, offer=22.696044788300803,up=true} on destination: topic://STOCKS.ORCL
Sending: {price=22.783456638853973, stock=ORCL, offer=22.806240095492825,up=true} on destination: topic://STOCKS.ORCL
Sending: {price=35.92652907541019, stock=CSCO, offer=35.96245560448559,up=false} on destination: topic://STOCKS.CSCO
Sending: {price=35.81608910812595, stock=CSCO, offer=35.851905197234075,up=false} on destination: topic://STOCKS.CSCO
Sending: {price=35.49430393012775, stock=CSCO, offer=35.52979823405787,up=false} on destination: topic://STOCKS.CSCO
Sending: {price=22.613210876407855, stock=ORCL, offer=22.63582408728426,up=false} on destination: topic://STOCKS.ORCL
Sending: {price=22.584893337535, stock=ORCL, offer=22.607478230872534,up=false} on destination: topic://STOCKS.ORCL
Sending: {price=35.81521985692496, stock=CSCO, offer=35.85103507678188,up=true} on destination: topic://STOCKS.CSCO
Sending: {price=35.8020033885887, stock=CSCO, offer=35.837805391977284,up=false} on destination: topic://STOCKS.CSCO
Sending: {price=22.570064862430183, stock=ORCL, offer=22.59263492729261,up=false} on destination: topic://STOCKS.ORCL
Published '10' of '10' price messages
...
 As expected, the publisher successfully sends stock portfolio updates to the broker inthis case. Now let’s see how to start a consumer with a proper certificate:  正如我们预期的那样,publisher能够成功的发送股票更新信息到代理.下面,再看看如何使用适当的证书启动consumer:
$ mvn -Djavax.net.ssl.keyStore=\
src/main/resources/org/apache/activemq/book/ch6/myconsumer.ks \
-Djavax.net.ssl.keyStorePassword=test123 \
-Djavax.net.ssl.trustStor${ACTIVEMQ_HOME}/conf/myclient.ts \
-Djavax.net.ssl.trustStorePassword=test123 exec:java \
-Dexec.mainClass=org.apache.activemq.book.ch4.Consumer \
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
 
(window dos 命令:
 
mvn -Djavax.net.ssl.keyStore=src/main/resources/org/apache/activemq/book/ch6/myconsumer.ks ^
-Djavax.net.ssl.keyStorePassword=test123 -Djavax.net.ssl.trustStore=src/main/resources/org/apache/activemq/book/ch6/myclient.ts ^
-Djavax.net.ssl.trustStorePassword=test123 exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer ^
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
)
...
ORCL 82.20 82.28 up
CSCO 88.52 88.61 down
CSCO 89.10 89.19 up
ORCL 81.90 81.98 down
ORCL 81.16 81.24 down
CSCO 89.84 89.93 up
ORCL 81.19 81.27 up
ORCL 81.38 81.46 up
CSCO 90.14 90.23 up
ORCL 81.03 81.12 down
ORCL 80.71 80.79 down
ORCL 80.01 80.09 down
ORCL 79.51 79.59 down
CSCO 90.52 90.61 up
ORCL 79.52 79.60 up
ORCL 78.77 78.85 down
...

Finally, we can test that our authorization settings work fine. As you can see from ourbroker configuration, consumers shouldn’t be allowed to send messages to our stockrelatedtopics. So if you try to do it, the operation should fail:

最后,可以看到我们的认证机制工作正常.从代理的配置文件中可以看出,消息消费者不允许发送消息到股票相关的主题,所以,假如你尝试让消息消费者发送消息将不会成功:

$ mvn -Djavax.net.ssl.keyStore=\
src/main/resources/org/apache/activemq/book/ch6/myconsumer.ks \
-Djavax.net.ssl.keyStorePassword=test123 \
-Djavax.net.ssl.trustStore=${ACTIVEMQ_HOME}/conf/myclient.ts \
-Djavax.net.ssl.trustStorePassword=test123 exec:java \
-Dexec.mainClass=org.apache.activemq.book.ch4.Publisher \
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
 
(译注:dos命令
mvn -Djavax.net.ssl.keyStore=src/main/resources/org/apache/activemq/book/ch6/myconsumer.ks ^
-Djavax.net.ssl.keyStorePassword=test123 -Djavax.net.ssl.trustStore=src/main/resources/org/apache/activemq/book/ch6/myclient.ts ^
-Djavax.net.ssl.trustStorePassword=test123 exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher ^
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
)
 
...
User CN=consumer, OU=Chapter 6, O=ActiveMQ in Action,
L=Belgrade, ST=Unknown, C=RS is not authorized to write to:topic://STOCKS.CSCO
...

 In this section, we learned how to leverage what we knew about the SSL transport (andconfiguring certificates) and with a bit of work configured certificate-based securityfor the ActiveMQ broker. This brings ActiveMQ security to an entirely new level andmakes it a perfect fit for organizations with tight security requirements.

本节中,我们学习了如何根据已知的关于SSL传输连接器相关知识(以及配置证书)来为ActiveMQ配置基于证书的安全机制.这样ActiveMQ的安全性提升到了一个新的高度,使得ActiveMQ可以更好的满足对安全型要求更高的需求.

赞 赏

   微信赞赏  支付宝赞赏


本文固定链接: https://www.jack-yin.com/coding/translation/activemq-in-action/1525.html | 边城网事

该日志由 边城网事 于2013年10月30日发表在 ActiveMQ in Action 读书笔记 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 6.4 基于证书的安全授权机制- Certificate -based security | 边城网事

6.4 基于证书的安全授权机制- Certificate -based security 暂无评论

发表评论

快捷键:Ctrl+Enter