Chinaunix首页 | 论坛 | 博客
  • 博客访问: 703973
  • 博文数量: 147
  • 博客积分: 6010
  • 博客等级: 准将
  • 技术积分: 1725
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-22 10:36
文章分类

全部博文(147)

文章存档

2011年(1)

2010年(1)

2009年(35)

2008年(110)

我的朋友

分类: Java

2008-12-19 17:17:43

   在启用了双向X.509认证后,无论是客户端还是Java EE服务端,他们都需要相互验证各自的身份(公钥证书),在采用X.509认证期间,传递的所有数据将受到SSL/TLS传输通道的保护,从而最大限度的保证了系统的安全!
   在实际应用中,X.509 CA证书大量地应用于HTTPS(TLS/SSL)中,并将它们安装到各个浏览器中。一旦浏览器接收到服务器提供的X.509 CA证书时,浏览器会根据自身维护的“trustStore”来验证证书的合法性:如果浏览器不能够自动验证它的合法身份,则交由浏览器客户手动完成。在启用双向SSL认证时,浏览器会客户还必须将自身的X.509证书提交到服务器中,此时服务器根据自身维护的“trustStore”来验证证书的合法性。
 
一.准备X.509证书:
前提在apps目录下创建三个目录:root server client
创建root证书:
Java代码
创建私钥 :C:\OpenSSL\apps>openssl genrsa -out root/root-key.pem 1024  
  1. 创建证书请求 :C:\OpenSSL\apps>openssl req -new -out root/root-req.csr -key root/root-key.pem   
  2. 自签署证书 :C:\OpenSSL\apps>openssl x509 -req -in root/root-req.csr -out root/root-cert.pem -signkey root/root-key.pem -days 3650  
  3. 将证书导出成浏览器支持的.p12格式 :C:\OpenSSL\apps>openssl pkcs12 -export -clcerts -in root/root-cert.pem -inkey root/root-key.pem -out root/root.p12   
  4. 打印自签证书 : C:\OpenSSL\apps>keytool -printcert -file root/root-cert.pem  
创建server证书:
Java代码
  1. 创建私钥 :C:\OpenSSL\apps>openssl genrsa -out server/server-key.pem 1024  
  2. 创建证书请求 :C:\OpenSSL\apps>openssl req -new -out server/server-req.csr -key server/server-key.pem   
  3. 自签署证书 :C:\OpenSSL\apps>openssl x509 -req -in server/server-req.csr -out server/server-cert.pem -signkey server/server-key.pem -CA root/root-cert.pem -CAkey root/root-key.pem -CAcreateserial -days 3650  
  4. 将证书导出成浏览器支持的.p12格式 :C:\OpenSSL\apps>openssl pkcs12 -export -clcerts -in server/server-cert.pem -inkey server/server-key.pem -out server/server.p12   
  5. 打印自签证书 : C:\OpenSSL\apps>keytool -printcert -file server/server-cert.pem  

创建client证书:
Java代码
  1. 创建私钥 :C:\OpenSSL\apps>openssl genrsa -out client/client-key.pem 1024  
  2. 创建证书请求 :C:\OpenSSL\apps>openssl req -new -out client/client-req.csr -key client/client-key.pem   
  3. 自签署证书 :C:\OpenSSL\apps>openssl x509 -req -in client/client-req.csr -out client/client-cert.pem -signkey client/client-key.pem -CA root/root-cert.pem -CAkey root/root-key.pem -CAcreateserial -days 3650  
  4. 将证书导出成浏览器支持的.p12格式 :C:\OpenSSL\apps>openssl pkcs12 -export -clcerts -in client/client-cert.pem -inkey client/client-key.pem -out client/client.p12   
  5. 打印自签证书 : C:\OpenSSL\apps>keytool -printcert -file client/client-cert.pem  

这一步是可选的,根据root证书生成JKS文件
生成JKS文件 :
Java代码
  1. C:\OpenSSL\apps\root>keytool -import -v -trustcacerts -storepass password -alias root -file root-cert.pem -keystore root.jks  
把root.jks,root.p12,server.p12三个文件复制到C:\tomcat\conf目录去

启动tomcat SSL的配置,在server.xml中更改配置为:
Java代码
  1. "8443" maxHttpHeaderSize="8192"  
  2.                maxThreads="150" minSpareThreads="25" maxSpareThreads="75"  
  3.                enableLookups="false" disableUploadTimeout="true"  
  4.                acceptCount="100" scheme="https" secure="true"  
  5.                sslProtocol="TLS"  
  6.                clientAuth="true" keystoreFile="C:/tomcat/conf/server.p12"  
  7.                keystoreType="PKCS12" keystorePass="password"  
  8.                truststoreFile="C:/tomcat/conf/root.jks"  
  9.                truststoreType="JKS" truststorePass="password" />  

经过以上步骤后,Tomcat服务器身份和根证书就算搞定了,但是客户身份换没有搞定。我们要把client.p12和root.p12导入到浏览器中去。
操作步骤为:打开IE->Internet选项->内容->证书
Java代码
  1. client.p12导入:

  

2.root.p12导入
  
完成以上步骤后,可以访问 了,不出意外就能看到你想要的结果

1:要想启用acegi X.509双向认证,就需要配置X509ProcessingFilter过滤器。
Java代码

    <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
          <property name="filterInvocationDefinitionSource">
             <value>
             CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
             PATTERN_TYPE_APACHE_ANT
                /**=channelProcessingFilter,httpSessionContextIntegrationFilter,logoutFilter,x509ProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
             </value>
          </property>
        </bean>

       <!-- ======================== AUTHENTICATION ======================= -->

       <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
          <property name="providers">
             <list>
             <ref local="x509AuthenticationProvider"/>
             </list>
          </property>
       </bean>
    <bean id="x509ProcessingFilter" class="org.acegisecurity.ui.x509.X509ProcessingFilter">
            <property name="authenticationManager"><ref local="authenticationManager"/></property>
        </bean>

    2.定义X509AuthenticationProcider认证提供者

    <bean id="x509AuthenticationProvider" class="org.acegisecurity.providers.x509.X509AuthenticationProvider">
            <property name="x509AuthoritiesPopulator"><ref local="x509AuthoritiesPopulator"/></property>
            <property name="x509UserCache"><ref local="x509UserCache"/></property>
        </bean>

        <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>

        <bean id="x509UserCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
           <property name="cacheManager">
              <ref local="cacheManager"/>
           </property>
           <property name="cacheName">
              <value>x509Cache</value>
           </property>
        </bean>

        <bean id="x509UserCache" class="org.acegisecurity.providers.x509.cache.EhCacheBasedX509UserCache">
          <property name="cache"><ref local="x509UserCacheBackend"/></property>
        </bean>

        <bean id="x509AuthoritiesPopulator" class="org.acegisecurity.providers.x509.populator.DaoX509AuthoritiesPopulator">
            <property name="userDetailsService"><ref local="jdbcDaoImpl"/></property>
          <!-- <property name="subjectDNRegex"><value>emailAddress=(.*?),</value></property> -->
        </bean>


         
      

    3.配置EhCacheBasedX509UserCache

    如上面

    4.将X509ProcessingFilterEntryPoint对象提供给ExceptionTranslationFilter

    <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
            <property name="authenticationEntryPoint"><ref local="x509ProcessingFilterEntryPoint"/></property>
        </bean>

    <bean id="x509ProcessingFilterEntryPoint" class="org.acegisecurity.ui.x509.X509ProcessingFilterEntryPoint">
        </bean>

    5.将X509ProcessingFilter过滤器添加到FilterChainProxy过滤器中

    6.启用SSL传输通道

    <bean id="channelProcessingFilter" class="org.acegisecurity.securechannel.ChannelProcessingFilter">
            <property name="channelDecisionManager"><ref local="channelDecisionManager"/></property>
             <property name="filterInvocationDefinitionSource">
                <value>
                 CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                    \A/secure/.*\Z=REQUIRES_SECURE_CHANNEL

                    
                    \A.*\Z=REQUIRES_INSECURE_CHANNEL
                </value>
            </property>
        </bean>

        <bean id="channelDecisionManager" class="org.acegisecurity.securechannel.ChannelDecisionManagerImpl">
         <property name="channelProcessors">
                  <list>
              <ref local="secureChannelProcessor"/>
                    <ref local="insecureChannelProcessor"/>
                 </list>
         </property>
        </bean>

        <bean id="secureChannelProcessor" class="org.acegisecurity.securechannel.SecureChannelProcessor">
        </bean>
        
        <bean id="insecureChannelProcessor" class="org.acegisecurity.securechannel.InsecureChannelProcessor">
        </bean>

    解决JavaEE各容器间端口的差异性:

    不同的JavaEE容器,默认时,他们服务HTTP和HTTPS请求的端口存在很大差别。比如:BEA WebLogic会采用7001(HTTP)/7002(HTTPS)组合,Tomcat(JBoss)会采用8080(HTTP)/8443(HTTPS)组合。实际生产环境中,大部分企业都会使用80/443组合。Acegi默认时,内置的X509仅仅支持80/443,8080/8443组合。可以修改:

    <bean id="portResolver" class="org.acegisecurity.util.PortResolverImpl">
            <property name="portMapper" ref="portMapper"></property>
        </bean>
        
        <bean id="portMapper" class="org.acegisecurity.util.PortMapperImpl">
            <property name="portMappings">
                <map>
                    <entry key="80" value="443"/>
                    <entry key="7001" value="7002"/>
                    <entry key="8080" value="8443"/>
                    <entry key="9080" value="9443"/>
                </map>
            </property>
        </bean>

     

    <bean id="retryWithHttpsEntryPoint" class="org.acegisecurity.securechannel.RetryWithHttpsEntryPoint">
            <property name="portMapper" ref="portMapper"/>
            <property name="portResolver" ref="portResolver"></property>
        </bean>    

    <bean id="retryWithHttpEntryPoint" class="org.acegisecurity.securechannel.RetryWithHttpEntryPoint">
            <property name="portMapper" ref="portMapper"/>
            <property name="portResolver" ref="portResolver"></property>
        </bean>    

     

    <bean id="secureChannelProcessor" class="org.acegisecurity.securechannel.SecureChannelProcessor">
            <property name="entryPoint" ref="retryWithHttpsEntryPoint" ></property>
        </bean>

    <bean id="insecureChannelProcessor" class="org.acegisecurity.securechannel.InsecureChannelProcessor">
            <property name="entryPoint" ref="retryWithHttpEntryPoint" ></property>
        </bean>

    <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
            <property name="authenticationEntryPoint"><ref local="x509ProcessingFilterEntryPoint"/></property>
            <property name="portResolver" ref="portResolver"></property>
        </bean>

    阅读(1711) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~