mdi*_*bio 8 asp.net security wif .net-4.5
任何人都可以指向使用NT凭据主动发出RequestSecurityToken的示例代码 Thread.CurrentPrincipal as ClaimsPrincipal
吗?
该场景是一个启用了Windows身份验证的asp.net Web应用程序(因此有一个经过身份验证的WindowsIdentity).我的愿望是主动调用STS而不是启用passiveRedirect,并使用.Net 4.5身份库执行此操作.
大多数代码示例(例如,用于Windows Phone的Claims Helper或使用Active STS)使用username/pwd输入和UserNameWSTrustBinding设置凭据.
我认为解决方案可能涉及模拟或使用channelFactory.CreateChannelWithActAsToken()
从Windows标识创建的令牌调用.
- 当访问/ adfs/services/trust/13/windowsmixed端点时,以下.Net4.5代码确实获得了GenericXmlSecurityToken.但是,声明适用于运行站点的域帐户,而不是经过身份验证的用户的域帐户.当我将端点切换到/ adfs/services/trust/13/kerberossmixed时,我得到了"无法协商"的错误,如几个问题和论坛中所述,但我不能在.Net 4.5中应用任何提供的解决方案.其中一个未从Microsoft.IdentityModel移植过的类是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);
}
}
Run Code Online (Sandbox Code Playgroud)
对于@leastprivilege建议,我添加以下代码:
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.
}
Run Code Online (Sandbox Code Playgroud)
哪个失败,"调用者未通过服务进行身份验证".相同的STS将在被动重定向场景中对我的域帐户进行身份验证...因此,虽然我知道我做错了什么,但应该识别帐户本身.
更新:
我收到通知,这个问题收到了大量的意见,所以我将提供以下一个解决方法:虽然我们配置了服务器进行委派(如下面Dominick所建议的),但我们仍然没有克服双跳问题.如果我记得的话,我们在本地IT之上的简单网络管理政策遇到了障碍,任何企业都可能会遇到这种情况.因此,虽然不允许使用Windows身份验证对服务器进行双跳模拟,但可以使用基本身份验证通过双跃点模拟凭据.这可能是也可能不是可接受的情况(我们案例的内联网).如果你这样做,你会添加
msgBinding.Security.Message.NegotiateServiceCredential = true;
Run Code Online (Sandbox Code Playgroud)
到上面的ChannelBinding配置.
嗯——这实际上并不是一件小事。为此,您需要进行 Kerberos 模拟和委派。
首先是模仿。您需要对从 Thread.CurrentPrincipal 获取的 WindowsIdentity 调用 Impersonate()。
您可以通过调用 WindowsIdentity.GetCurrent 来确保您正在冒充。该身份必须指向客户端(而不是服务器身份)。
然后,在模拟时,您需要发出 WS-Trust 请求。默认情况下这很可能是不允许的。因此,您的网络管理员需要配置服务器身份对 STS 的委派。
归档时间: |
|
查看次数: |
4234 次 |
最近记录: |