RequestSecurityToken 使用 Windows 凭据和 .net 4.5 WIF [英] RequestSecurityToken using windows credentials and .net 4.5 WIF

查看:18
本文介绍了RequestSecurityToken 使用 Windows 凭据和 .net 4.5 WIF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能指出使用 Thread.CurrentPrincipal 作为 ClaimsPrincipal 的 NT 凭据主动发出 RequestSecurityToken 的示例代码?

Can anyone point to sample code for actively issuing a RequestSecurityToken using the NT credentials of the Thread.CurrentPrincipal as ClaimsPrincipal?

该场景是一个启用了 Windows 身份验证的 asp.net Web 应用程序(因此有一个经过身份验证的 WindowsIdentity).我的愿望是主动调用 STS 而不是启用passiveRedirect,并使用.Net 4.5 身份库来做到这一点.

The scenario is an asp.net web app with windows authentication enabled (so there is an authenticated WindowsIdentity). My desire is to call the STS actively rather than enabling passiveRedirect, and to do this using the .Net 4.5 identity libraries.

大多数代码示例,例如 Windows Phone 的索赔助手使用活动 STS 使用用户名/密码输入和 UserNameWSTrustBinding 设置凭据.

Most code samples, such as Claims Helper for Windows Phone or Using an Active STS set the credentials with a username/pwd input and UserNameWSTrustBinding.

我认为该解决方案可能涉及使用从 Windows 身份创建的令牌进行模拟或调用 channelFactory.CreateChannelWithActAsToken().

I thought the solution might involve impersonation or a call to channelFactory.CreateChannelWithActAsToken() with the a token created from the windows identity.

-- 当点击/adfs/services/trust/13/windowsmixed 端点时,以下 .Net4.5 代码确实获得了 GenericXmlSecurityToken.但是,声明是针对运行站点的域帐户,而不是经过身份验证的用户的域帐户.当我将端点切换到/adfs/services/trust/13/kerberossmixed 时,出现无法协商"错误,如多个问题和论坛中所述,但我无法将任何提供的解决方案应用于 .Net 4.5.未从 Microsoft.IdentityModel 移植过来的类之一是 KerberosWSTrustBinding...

-- The following .Net4.5 code does get a GenericXmlSecurityToken when hitting an /adfs/services/trust/13/windowsmixed endpoint. However, the claims are for the domain account under which the site is running, and not the domain account of the authenticated user. When I switch the endpoint to /adfs/services/trust/13/kerberossmixed, I get "cannot negotiate" errors as documented in several questions and forums, but I cannot apply any offered solutions with .Net 4.5. One of the classes not ported over from Microsoft.IdentityModel is the KerberosWSTrustBinding...

public static void CallSts()
{
    try
    {
        var wsMod = FederatedAuthentication.WSFederationAuthenticationModule;
        var appliesToEp = new EndpointReference(wsMod.Realm);
        var stsEp = new EndpointAddress(new Uri(wsMod.Issuer), EndpointIdentity.CreateSpnIdentity("stsSpn"));

        var msgBinding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential, false);
        msgBinding.Security.Message.EstablishSecurityContext = false;
        msgBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

        using(var factory = new WSTrustChannelFactory(msgBinding, stsEp))
        {
            factory.Credentials.SupportInteractive = false;
            factory.TrustVersion = TrustVersion.WSTrust13;

            var myRst = new RequestSecurityToken
            {
                RequestType = RequestTypes.Issue,
                AppliesTo = appliesToEp,
                KeyType = KeyTypes.Bearer,
            };
                var channel = factory.CreateChannel();
                var stsToken = channel.Issue(myRst) as GenericXmlSecurityToken;

                if(stsToken != null)
                {
                    Log.DebugFormat("Reply Token is {0}", stsToken.GetType().Name);

                    var handlers = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers;
                    var token = handlers.ReadToken(new XmlTextReader(new StringReader(stsToken.TokenXml.OuterXml)));
                    var identity = handlers.ValidateToken(token).First();
                    //TODO write to session
                }
                else
                {
                    Log.Debug("Reply Token is null.");
                }
        }
    }
    catch(Exception ex)
    {
        Log.Error("Rst.Call has failed", ex);
    }
}

对于@leastprivilege 建议,我添加以下代码:

For @leastprivilege suggestion, I add this code:

    var user = Thread.CurrentPrincipal as ClaimsPrincipal;
var winId = user.Identity as WindowsIdentity;
if(winId != null)
{
    // shows my domain account after I was prompted for credentials;
    // my domain account does not exist on the client machine, so it is a true domain credential
    Log.DebugFormat("WindowsIdentity Name is {0}", winId.Name);
}
using(winId.Impersonate())
{
    // again, shows my domain account
    Log.DebugFormat("Impersonation Context {0}", WindowsIdentity.GetCurrent(true).Name);
    var channel = factory.CreateChannel();
    var stsToken = channel.Issue(myRst) as GenericXmlSecurityToken;
    // request is issued, but results in SecurityNegotiationException: The caller was not authenticated by the service.
}

失败并显示调用方未通过服务进行身份验证".相同的 STS 将在被动重定向场景中验证我的域帐户......所以虽然我知道我做错了什么,但帐户本身应该被识别.

Which fails with "The caller was not authenticated by the service". The same STS will authenticate my domain account in a passive redirect scenario...so although I know I am doing something wrong, the account itself should be recognized.

更新:

我收到通知说这个问题获得了大量的浏览量,因此我将提供以下解决方法:尽管我们为委托配置了我们的服务器(正如 Dominick 在下面建议的那样),我们仍然没有克服双跳问题.如果我记得,我们在本地 IT 之上的简单网络管理策略遇到了任何企业都可能遇到的障碍.因此,虽然不允许通过双跳模拟使用 Windows 身份验证的服务器,但可以使用基本身份验证通过双跳模拟凭据.这可能是也可能不是可接受的情况(对于我们的案例是内联网).如果你这样做,你会添加

I received a notification that this question received a notable number of views, so I will offer the following as one workaround: Although we configured our servers for delegation (as Dominick suggested below), we still did not surmount the double-hop issue. If I remember, we hit a roadblock from simple network management policies above our local IT that any enterprise might hit as well. So, while impersonating over a double-hop against a server with Windows Authentication is not allowed, credentials can be impersonated over a double hop using Basic Authentication. This may or may not be an acceptable situation (intranet for our case). If you do, you would add

msgBinding.Security.Message.NegotiateServiceCredential = true;

到上面的ChannelBinding配置.

to the above ChannelBinding configuration.

推荐答案

嗯 - 这实际上不是微不足道的.为此,您需要进行 Kerberos 模拟和委托.

Well - This is actually not trivial. You need to do Kerberos impersonation and delegation for that.

首先是模仿.您需要在从 Thread.CurrentPrincipal 获得的 WindowsIdentity 上调用 Impersonate().

First of all impersonation. You need to call Impersonate() on the WindowsIdentity you get from Thread.CurrentPrincipal.

您可以通过调用 WindowsIdentity.GetCurrent 来确保您正在模拟.这个身份必须指向客户端(而不是服务器身份).

You can make sure you are impersonating by calling WindowsIdentity.GetCurrent. This identity must point to the client then (as opposed to the server identity).

然后在模拟时您需要发出 WS-Trust 请求.这很可能是默认不允许的.因此,您的网络管理员需要为 STS 的服务器身份配置委派.

Then while impersonating you need to make the WS-Trust request. This is most probably not allowed by default. So you network admin needs to configure delegation for the sever identity to the STS.

这篇关于RequestSecurityToken 使用 Windows 凭据和 .net 4.5 WIF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆