Как получить сертификат X509 из запроса клиента - PullRequest
15 голосов
/ 23 сентября 2011

У меня есть веб-сервис, который я защищал с помощью сертификатов. Теперь я хочу идентифицировать клиента, посмотрев на отпечаток сертификата. Это означает, что у меня есть список отпечатков на моем сервисе, который связан с каким-то пользователем.

На самом деле, мой первый вопрос (немного не по теме): это хороший подход, или я все же должен ввести некоторую конструкцию пароля пользователя?

Второй вопрос: как я могу получить сертификат, который клиент использовал для подключения к веб-сервису, чтобы я мог прочитать отпечаток на стороне сервиса.

Я много об этом читал (например, этот пост: Как получить сертификат X509, отправленный с клиента в веб-сервисе? ), но не смог найти ответ.

У меня нет HTTPContext, так что это не вариант. В упомянутом выше посте говорится о Context.Request.ClientCertificate.Certificate, но я думаю, что они также имеют в виду HTTPContext. Также добавление <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> к web.config также не вариант.

Ответы [ 2 ]

20 голосов
/ 23 сентября 2011

вот как мы это делаем в конструкторе нашего веб-сервиса:

if (OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets == null)
    throw new SecurityException ("No claimset service configured wrong");

if (OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets.Count <= 0)
    throw new SecurityException ("No claimset service configured wrong");


var cert = ((X509CertificateClaimSet) OperationContext.Current.ServiceSecurityContext.
            AuthorizationContext.ClaimSets[0]).X509Certificate;

//this contains the thumbprint
cert.Thumbprint
4 голосов
/ 23 сентября 2011

Я не думаю, что с этим подходом что-то не так, если этот сервис используется в среде, где вы можете контролировать распространение сертификатов и обеспечивать их безопасное хранение.

Предполагая, что это WCFсервис, вы можете получить сертификат, который клиент представляет, используя класс, который наследуется от ServiceAuthorizationManager.Примерно так будет работать:

public class CertificateAuthorizationManager : ServiceAuthorizationManager
{
    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        if (!base.CheckAccessCore(operationContext))
        {
            return false;
        }

        string thumbprint = GetCertificateThumbprint(operationContext);

        // TODO: Check the thumbprint against your database, then return true if found, otherwise false
    }

    private string GetCertificateThumbprint(OperationContext operationContext)
    {
        foreach (var claimSet in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
        {
            foreach (Claim claim in claimSet.FindClaims(ClaimTypes.Thumbprint, Rights.Identity))
            {
                string tb = BitConverter.ToString((byte[])claim.Resource);
                tb = tb.Replace("-", "");
                return tb;
            }
        }

        throw new System.Security.SecurityException("No client certificate found");
    }
}

Затем вам нужно изменить конфигурацию на сервере, чтобы использовать этот менеджер авторизации:

<system.serviceModel>

    <behaviors>
        <serviceBehaviors>
            <behavior name="MyServerBehavior">

                <serviceAuthorization serviceAuthorizationManagerType="myNamespace.CertificateAuthorizationManager, myAssembly"/>

                ...

            </behavior>
        </serviceBehaviors>
    </behaviors>

    ...

</system.serviceModel>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...