我在同一主机上的IIS6中托管了几个WCF服务(不应该影响这个问题),我希望,由于性能/维护和其他原因,使用Facade Service将多个请求合并为1个请求, 所有这些都是通过特殊的服务合同/服务完成的,该服务合同/服务的操作可以调用其他服
我正在使用带有Message安全性和UserName客户端凭据类型的WSHTTP(可能在不久的将来使用BasicHttp)。
我希望Facade Service使用来自客户端的凭据。这意味着对后端服务的调用将获得凭证,就好像客户端将直接调用它一样。
例如: 客户端使用UserName“A”和密码“B”调用FacadeService.CompositeOperation。 现在,FacadeService.CompositeOperation需要调用BackEndService.BackendOperation,将Credentials.UserName.UserName设置为“A”,将Credentials.UserName.Password设置为“B”,就像客户端在调用此操作时所做的那样。我无法在WCF中提取此信息(它应该是,因为它是敏感信息)但我既没有找到一种方法来获取这些信息的“令牌”并将其传递给后端服务(我没有必要在FacadeService中知道这些信息,只传递它们。
在FacadeService中,与BackEndService一样,身份验证是通过ASP.NET提供程序进行的,授权是从PrimaryIdentity获取UserName的自定义基于角色的授权,因此BackEndService上的PrimaryIdentity应设置为客户端发送的内容
我该怎么做?
答案 0 :(得分:0)
我昨天看了你的帖子,但不确定答案,但看到你没有回复,我以为我会添加一些东西,也许会提供一些思考的东西。
首先,是否会使附加服务调用对资源过度密集?如果没有,那么代码清晰度存在争议,将它们分开,以便将来开发人员将确切知道发生了什么,而不是执行多个操作的1个服务调用。
您是否无法从您正在使用的方法中调用服务器端代码中的其他服务?曾经,你是服务器端,安全上下文应该保存你所使用的用户的身份,因此对其他服务的调用将使用相同的身份。
最后,我想知道是否可以在服务器上使用WCF模拟(MSDN LINK)来实现您所追求的目标。我自己没有使用它,所以不能像我想的那样建议。
希望有所帮助 - 祝你好运!
答案 1 :(得分:0)
我试图在PrimaryIdentity中将密码与UserName一起存储。 为此,我们需要做的是提供一个新的UserNameSecurityTokenAuthenticator,它将验证UserName和Password,然后可以存储在Identity中,然后它将Identity存储在WCF的SecurityContext中。
要做的步骤
课程
1。)TestServiceHost:ServiceHost
2。)UserNamePasswordSecurityTokenManager:ServiceCredentialsSecurityTokenManager
3。)TestUserNameSecurityTokenAuthenticator:UserNameSecurityTokenAuthenticator
4。)MyIdentity:IIdentity
5.。)MyAuthorizatoinPolicy:IAuthorizationPolicy
1。)创建新的ServiceHost类TestServiceHost
2.。)在TestServiceHost中覆盖OnOpening并提供一个新的类UserNamePasswordServiceCredentials
protected override void OnOpening()
{
base.OnOpening();
this.Description.Behaviors.Add(new UserNamePasswordServiceCredentials());
}
3.)然后在UserNamePasswordServiceCredentials中,提供新的UserNamePasswordSecurityTokenManager
public override SecurityTokenManager CreateSecurityTokenManager()
{
return new UserNamePasswordSecurityTokenManager(this);
}
4.)然后在UserNamePasswordSecurityTokenManager中提供新的TestUserNameSecurityTokenAuthenticator
public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
{
if (tokenRequirement.TokenType == SecurityTokenTypes.UserName)
{
outOfBandTokenResolver = null;
return new TestUserNameSecurityTokenAuthenticator();
}
return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver);
}
5.)然后在TestUserNameSecurityTokenAuthenticator内,您可以验证UseraName和密码,并可以创建自己的身份。在此函数中,您将返回要评估的IAuthorization策略列表。我创建了自己的授权策略并将新身份传递给它,以便在上下文中设置身份。
protected override System.Collections.ObjectModel.ReadOnlyCollection<System.IdentityModel.Policy.IAuthorizationPolicy> ValidateUserNamePasswordCore(string userName, string password)
{
ClaimSet claimSet = new DefaultClaimSet(ClaimSet.System, new Claim(ClaimTypes.Name, userName, Rights.PossessProperty));
List<IIdentity> identities = new List<IIdentity>(1);
identities.Add(new MyIdentity(userName,password));
List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1);
policies.Add(new MyAuthorizationPolicy(ClaimSet.System, identities));
return policies.AsReadOnly();
}
public class MyAuthorizationPolicy : IAuthorizationPolicy
{
String id = Guid.NewGuid().ToString();
ClaimSet issuer;
private IList<IIdentity> identities;
#region IAuthorizationPolicy Members
public MyAuthorizationPolicy(ClaimSet issuer, IList<IIdentity> identities)
{
if (issuer == null)
throw new ArgumentNullException("issuer");
this.issuer = issuer;
this.identities = identities;
}
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
if (this.identities != null)
{
object value;
IList<IIdentity> contextIdentities;
if (!evaluationContext.Properties.TryGetValue("Identities", out value))
{
contextIdentities = new List<IIdentity>(this.identities.Count);
evaluationContext.Properties.Add("Identities", contextIdentities);
}
else
{
contextIdentities = value as IList<IIdentity>;
}
foreach (IIdentity identity in this.identities)
{
contextIdentities.Add(identity);
}
}
return true;
}
public ClaimSet Issuer
{
get { return this.issuer; }
}
#endregion
#region IAuthorizationComponent Members
public string Id
{
get { return this.id; }
}
#endregion
}
因此,此示例显示了如何在WCF中覆盖安全性:
现在问题在于:
1。)实施此技术并在您的身份中设置用户名和密码。现在,当您有呼叫子服务时,从中获取身份提取用户名和密码并传递给子服务。
2。)验证UserName和Password并为其生成令牌(应为此创建新的令牌服务)。将此令牌与用户名一起保存在您的标识中,并将这两个标记传递给您的子服务。现在,为了使这种方法起作用,子服务必须验证您新生成的令牌,您应该拥有令牌服务,该服务可以通过验证用户名和密码来创建令牌,还可以使用用户名验证令牌。
我个人会选择方法2,但会引入新的开销。