Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自托管Owin端点中的客户端证书映射身份验证_C#_Ssl_Active Directory_Owin_Katana - Fatal编程技术网

C# 自托管Owin端点中的客户端证书映射身份验证

C# 自托管Owin端点中的客户端证书映射身份验证,c#,ssl,active-directory,owin,katana,C#,Ssl,Active Directory,Owin,Katana,是否可以(如果可以,如何配置)将自托管owin端点配置为与a/D一起使用客户端证书映射身份验证?IIS具有此功能,但到目前为止,我还没有找到用于自托管端点的等效功能 不过,我实现这一点的方法(请记住,这种方法可能不是100%万无一失的),是一个两步过程,使用authenticationSchemeSelectorDelegate和OWIN的组合 这将选择适当的AuthenticationScheme(允许通过包含证书的请求,否则将推迟到NTLM身份验证) 这将读取证书的内容并相应地填充“serv

是否可以(如果可以,如何配置)将自托管owin端点配置为与a/D一起使用客户端证书映射身份验证?IIS具有此功能,但到目前为止,我还没有找到用于自托管端点的等效功能

不过,我实现这一点的方法(请记住,这种方法可能不是100%万无一失的),是一个两步过程,使用authenticationSchemeSelectorDelegate和OWIN的组合

这将选择适当的AuthenticationScheme(允许通过包含证书的请求,否则将推迟到NTLM身份验证)

这将读取证书的内容并相应地填充“server.User”环境变量

公共类证书认证器
{
只读函数_appFunc;
公共证书认证器(Func appFunc)
{
_appFunc=appFunc;
}
公共任务调用(IDictionary环境)
{
//我们是否已通过身份验证(NTLM)
var user=environment[“server.user”]作为IPrincipal;
if(user!=null&&user.Identity.IsAuthenticated)返回_appFunc.Invoke(环境);
var context=environment[“System.Net.HttpListenerContext”]作为HttpListenerContext;
if(context==null)返回_appFunc.Invoke(环境);
var clientCertificate=context.Request.GetClientCertificate();
//从证书中解析出用户名
var identity=新的GenericPrincipal
(
新GenericEntity(用户名),新字符串[0]
);
环境[“server.User”]=标识;
}
}

没有更好的/标准化的方法吗?

我还没有看到任何为此构建的标准组件。也就是说,应该可以稍微清理一下代码:

  • 您不需要向下转换到HttpListenerContext来获取客户端证书。客户端证书应该已经在OWIN环境中的“ssl.ClientCertificate”下可用。看见您还需要检查ssl.ClientCertificateErrors,因为证书可能未通过所有验证检查
  • 您不需要AuthenticationSchemeSelectorDelegate代码。您可以只设置listner.AuthenticationSchemes=NTLM | Anonymous。然后在证书中间件之后添加一个中间件,该中间件返回401 if server.User无效
public void Configuration(IAppBuilder appBuilder)
{
    var listener = (HttpListener)appBuilder.Properties[typeof(HttpListener).FullName];
    listener.AuthenticationSchemeSelectorDelegate += AuthenticationSchemeSelectorDelegate;
}

private AuthenticationSchemes AuthenticationSchemeSelectorDelegate(HttpListenerRequest httpRequest)
{
    if (!httpRequest.IsSecureConnection) return AuthenticationSchemes.Ntlm;
    var clientCert = httpRequest.GetClientCertificate();
    if (clientCert == null) return AuthenticationSchemes.Ntlm;
    else return AuthenticationSchemes.Anonymous;
}
public class CertificateAuthenticator
{
    readonly Func<IDictionary<string, object>, Task> _appFunc;

    public CertificateAuthenticator(Func<IDictionary<string, object>, Task> appFunc)
    {
        _appFunc = appFunc;
    }

    public Task Invoke(IDictionary<string, object> environment)
    {
        // Are we authenticated already (NTLM)
        var user = environment["server.User"] as IPrincipal;
        if (user != null && user.Identity.IsAuthenticated) return _appFunc.Invoke(environment);

        var context = environment["System.Net.HttpListenerContext"] as HttpListenerContext;
        if (context == null) return _appFunc.Invoke(environment);

        var clientCertificate = context.Request.GetClientCertificate();

        // Parse out username from certificate

        var identity = new GenericPrincipal
        (
            new GenericIdentity(username), new string[0]
        );

        environment["server.User"] = identity;
    }
}