Видимо, я задал неправильный вопрос в своем предыдущем посте. У меня есть веб-служба, защищенная сертификатом X.509, работающая как безопасный веб-сайт (https://... ). Я хочу использовать сертификат клиентского компьютера (также X.509), выданный корневым ЦС компании, чтобы подтвердить серверу, что клиентский компьютер авторизован для использования службы. Для этого мне нужно проверить сертификат и найти какую-либо идентифицирующую функцию и сопоставить ее со значением, хранящимся в базе данных (может быть, с отпечатком пальца?).
Вот код, который я использую для получения сертификата из локального хранилища сертификатов (взято прямо из http://msdn.microsoft.com/en-us/magazine/cc163454.aspx):
public static class SecurityCertificate
{
private static X509Certificate2 _certificate = null;
public static X509Certificate2 Certificate
{
get { return _certificate; }
}
public static bool LoadCertificate()
{
// get thumbprint from app.config
string thumbPrint = Properties.Settings.Default.Thumbprint;
if ( string.IsNullOrEmpty( thumbPrint ) )
{
// if no thumbprint on file, user must select certificate to use
_certificate = PickCertificate( StoreLocation.LocalMachine, StoreName.My );
if ( null != _certificate )
{
// show certificate details dialog
X509Certificate2UI.DisplayCertificate( _certificate );
Properties.Settings.Default.Thumbprint = _certificate.Thumbprint;
Properties.Settings.Default.Save();
}
}
else
{
_certificate = FindCertificate( StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, thumbPrint );
}
if ( null == _certificate )
{
MessageBox.Show( "You must have a valid machine certificate to use STS." );
return false;
}
return true;
}
private static X509Certificate2 PickCertificate( StoreLocation location, StoreName name )
{
X509Store store = new X509Store( name, location );
try
{
// create and open store for read-only access
store.Open( OpenFlags.ReadOnly );
X509Certificate2Collection coll = store.Certificates.Find( X509FindType.FindByIssuerName, STSClientConstants.NBCCA, true );
if ( 0 == coll.Count )
{
MessageBox.Show( "No valid machine certificate found - please contact tech support." );
return null;
}
// pick a certificate from the store
coll = null;
while ( null == coll || 0 == coll.Count )
{
coll = X509Certificate2UI.SelectFromCollection(
store.Certificates, "Local Machine Certificates",
"Select one", X509SelectionFlag.SingleSelection );
}
// return first certificate found
return coll[ 0 ];
}
// always close the store
finally { store.Close(); }
}
private static X509Certificate2 FindCertificate( StoreLocation location, StoreName name, X509FindType findType, string findValue )
{
X509Store store = new X509Store( name, location );
try
{
// create and open store for read-only access
store.Open( OpenFlags.ReadOnly );
// search store
X509Certificate2Collection col = store.Certificates.Find( findType, findValue, true );
// return first certificate found
return col[ 0 ];
}
// always close the store
finally { store.Close(); }
}
Затем я прикрепляю сертификат к исходящему потоку следующим образом:
public static class ServiceDataAccess
{
private static STSWebService _stsWebService = new STSWebService();
public static DataSet GetData(Dictionary<string,string> DictParam, string action)
{
// add the machine certificate here, the first web service call made by the program (only called once)
_stsWebService.ClientCertificates.Add( SecurityCertificate.Certificate );
// rest of web service call here...
}
}
Мой вопрос заключается в следующем: как мне «получить» сертификат в коде веб-службы? В большинстве фрагментов кода, с которыми я сталкивался, рассказывается, как выполнить пользовательскую проверку, есть вызов GetCertificate(), очевидно, предполагая, что эта часть настолько проста, что все должны знать, как это сделать?
Мой основной класс наследуется от WebService, поэтому я могу использовать Context.Request.ClientCertificate для получения сертификата, но это HttpClientCertificate, а не X509Certificate2. HttpContext дает мне тот же результат. Все другие подходы используют код веб-конфигурации для вызова предопределенного кода проверки, не имея представления о том, как вызвать пользовательский метод C# для выполнения проверки.