Client certificate authentication over https is fa

2019-05-06 14:26发布

I'm attempting to get https client authentication working using this sample code in Python 2.7. Unfortunately, the client script doesn't appear to be authenticating correctly and I've not been able to track down why.

I generated a test CA and server/client certificates as follows:

# Generate CA key and certificate
openssl genrsa -des3 -out test.ca.key 8192
openssl req -new -key test.ca.key -x509 -days 30 -out test.ca.crt

# Generate server key and certificate
openssl genrsa -out www.testsite.com.key 1024
openssl req -new -key www.testsite.com.key -out www.testsite.com.csr
openssl x509 -req -days 30 -in www.testsite.com.csr -CA test.ca.crt -CAkey test.ca.key -CAcreateserial -out www.testsite.com.crt

# Generate client key and certificate
openssl genrsa -out testclient.key 1024
openssl req -new -key testclient.key -out testclient.csr
openssl x509 -req -days 30 -in testclient.csr -CA test.ca.crt -CAkey test.ca.key -CAcreateserial -out testclient.crt

Now if I generate a PKCS#12 certificate:

openssl pkcs12 -export -clcerts -in testclient.crt -inkey testclient.key -out testclient.p12

...and import testclient.p12 into Firefox, I can browse the test site as expected, so the server and keys would appear to be configured properly. However, when trying the sample code referenced above, as follows:

import urllib2, httplib

class HTTPSClientAuthHandler(urllib2.HTTPSHandler):
    def __init__(self, key, cert):
        urllib2.HTTPSHandler.__init__(self)
        self.key = key
        self.cert = cert
    def https_open(self, req):
        return self.do_open(self.getConnection, req)
    def getConnection(self, host, timeout=300):
        return httplib.HTTPSConnection(host, key_file=self.key, cert_file=self.cert)

opener = urllib2.build_opener(HTTPSClientAuthHandler('testclient.key', 'testclient.crt') )
response = opener.open("https://www.testsite.com/")
print response.read()

... I get a 403 error:

Traceback (most recent call last):
  File "./cert2.py", line 21, in <module>
    response = opener.open("https://www.testsite.com/")
  File "/usr/lib64/python2.6/urllib2.py", line 395, in open
    response = meth(req, response)
  File "/usr/lib64/python2.6/urllib2.py", line 508, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib64/python2.6/urllib2.py", line 433, in error
    return self._call_chain(*args)
  File "/usr/lib64/python2.6/urllib2.py", line 367, in _call_chain
    result = func(*args)
  File "/usr/lib64/python2.6/urllib2.py", line 516, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 403: Forbidden

Where did I go astray?

EDIT: Here's the site's Apache config:

<VirtualHost *:80>
  ServerAdmin webmaster@testsite.com
  ServerName www.testsite.com

  DocumentRoot /var/www/testsite/
  <Directory "/">
    Options FollowSymLinks
    AllowOverride None
  </Directory>

  RewriteEngine On
  RewriteCond %{SERVER_PORT} 80
  RewriteRule ^/?(.*) https://www.testsite.com/$1 [L]

  ErrorLog ${APACHE_LOG_DIR}/error.log
  LogLevel warn
  CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

<VirtualHost *:443>
  ServerAdmin webmaster@testsite.com

  DocumentRoot /var/www/testsite/
  ServerName www.testsite.com

  SSLEngine on
  SSLCertificateFile    /etc/ssl/certs/www.testsite.com.crt
  SSLCertificateKeyFile /etc/ssl/private/www.testsite.com.key
  SSLCertificateChainFile /etc/ssl/ca/test.ca.crt
  SSLCACertificateFile /etc/ssl/ca/test.ca.crt

  <Location />
    SSLRequireSSL
    SSLVerifyClient require
    SSLVerifyDepth 10
  </Location>

  <Directory />
    Options FollowSymLinks
    AllowOverride None
  </Directory>
  <Directory /var/www/testsite>
    Options FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
  </Directory>

  ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/testsite/
  <Directory "/usr/lib/cgi-bin/testsite">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
  </Directory>

  ErrorLog /var/log/apache2/error.log
  LogLevel warn
  CustomLog /var/log/apache2/access.log combined
</VirtualHost>

2条回答
祖国的老花朵
2楼-- · 2019-05-06 14:34

I think this isn't a cert issue. HTTP 403 (Forbidden) is already a http status code sent to you by the http server through the secured channel, so ssl seems to work fine. You are just trying to access something you are not authorized for.

Additional note: Check the same url in a browser too!

查看更多
地球回转人心会变
3楼-- · 2019-05-06 14:53

If you need a client in python you can use requests, in particular this.

import requests
resp = requests.get('https://www.testsite.com/', cert=('testclient.crt', 'testclient.key'))

print resp.status_code
print resp.text
查看更多
登录 后发表回答