如何将 WCF UserName clientCredentialType 传递给其他服务? [英] How to pass WCF UserName clientCredentialType to other service?

查看:57
本文介绍了如何将 WCF UserName clientCredentialType 传递给其他服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在同一主机上的 IIS6 中托管了多个 WCF 服务(不应影响此问题),出于性能/维护和其他原因,我希望使用 Facade 服务将多个请求合并为 1 个请求,所有这些都是通过特殊的服务合同/服务完成的,该服务具有为多个操作调用其他服务的操作.

I have several WCF services hosted in IIS6 (should not affect this issue) on the same host, and I want, for Performance/ Maintanance and other reasons to combine several requests into 1 request using a Facade Service, All done with special Service Contract / Service that has an operation that calls other services for several operations.

我正在使用具有消息安全性和用户名客户端凭据类型的 WSHTTP(在不久的将来可能会使用 BasicHttp).

I'm using WSHTTP (probably BasicHttp in the near future) with Message security and UserName client credential type.

我希望 Facade Service 使用来自客户端的凭据.这意味着对后端服务的调用将获得凭据,就像客户端将直接调用它一样.

I want the Facade Service to use the credentials from the client. Meaning the call to the back-end service will get the credentials as if the client would call it directly.

例如:客户端使用用户名A"和密码B"调用 FacadeService.CompositeOperation.现在 FacadeService.CompositeOperation 需要调用 BackEndService.BackendOperation,将 Credentials.UserName.UserName 设置为A",将 Credentials.UserName.Password 设置为B",就像客户端调用此操作时所做的那样.我无法在 WCF 中提取这些信息(应该是这样,因为它是敏感信息)但我都没有找到一种方法来获取这些信息的令牌"并将其传递给后端服务(我不需要在 FacadeService 中知道这些信息,只是为了传递它们).

For example: Client calls FacadeService.CompositeOperation with UserName "A" and password "B". Now the FacadeService.CompositeOperation needs to call BackEndService.BackendOperation setting the Credentials.UserName.UserName to "A" and Credentials.UserName.Password to "B" just like what the client done when calling to this operation. I have no way to extract this information in WCF (and it should be, because it is sensitive information) but i neither found a way to take "a token" of these and pass it forward to the backend service (I have no need to know this information in the FacadeService, only to pass them over).

在 FacadeService 中,与 BackEndService 一样,身份验证是通过 ASP.NET 提供程序进行的,授权是基于自定义角色的授权,从 PrimaryIdentity 中获取 UserName,因此 BackEndService 上的 PrimaryIdentity 应设置为客户端发送的内容.

In FacadeService, as in BackEndService, the authentication is made through ASP.NET provider, the authorization is a custom Role-based authorization taking the UserName from the PrimaryIdentity, so the PrimaryIdentity on the BackEndService should be set to what the client send.

我该怎么做?

推荐答案

有一次我尝试将 Password 和 UserName 一起存储在 PrimaryIdentity 中.为了实现这一点,我们需要做的是提供一个新的 UserNameSecurityTokenAuthenticator,它将验证用户名和密码,然后可以存储在身份中,然后将身份存储在 WCF 的 SecurityContext 中.

Once i tried to Store Password along with UserName in PrimaryIdentity. To achieve this What we need to do is to provide a New UserNameSecurityTokenAuthenticator Which will authenticate UserName and Password and then can store in the Identity and then it will Store the Identity in SecurityContext of WCF.

要做的步骤

课程

1.) TestServiceHost : ServiceHost

1.) TestServiceHost : ServiceHost

2.) UserNamePasswordSecurityTokenManager : ServiceCredentialsSecurityTokenManager

2.) UserNamePasswordSecurityTokenManager : ServiceCredentialsSecurityTokenManager

3.) TestUserNameSecurityTokenAuthenticator : UserNameSecurityTokenAuthenticator

3.) TestUserNameSecurityTokenAuthenticator : UserNameSecurityTokenAuthenticator

4.) MyIdentity : IIdentity

4.) MyIdentity : IIdentity

5.) 我的授权策略:IAuthorizationPolicy

5.) MyAuthorizatoinPolicy : IAuthorizationPolicy

1.) 创建新的 ServiceHost 类 TestServiceHost

1.) Create New ServiceHost class TestServiceHost

2.) 在 TestServiceHost 覆盖 OnOpening 并提供一个新的类 UserNamePasswordServiceCredentials

2.) In TestServiceHost Override OnOpening and provide a new Class UserNamePasswordServiceCredentials

protected override void OnOpening()
{
    base.OnOpening();
    this.Description.Behaviors.Add(new UserNamePasswordServiceCredentials());
}

3.) 然后在 UserNamePasswordServiceCredentials 中,提供新的 UserNamePasswordSecurityTokenManager

3.) Then in UserNamePasswordServiceCredentials, provide new UserNamePasswordSecurityTokenManager

public override SecurityTokenManager CreateSecurityTokenManager()
{
    return new UserNamePasswordSecurityTokenManager(this);
}

4.) 然后在 UserNamePasswordSecurityTokenManager 中提供新的 TestUserNameSecurityTokenAuthenticator

4.) Then in UserNamePasswordSecurityTokenManager provide new 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 和 Password 并创建您自己的身份.在此函数中,您将返回要评估的 IAuthorization 策略列表.我创建了自己的授权策略并将我的新身份传递给它,以便在上下文中设置身份.

5.) Then Inside TestUserNameSecurityTokenAuthenticator you can Authenticate UseraName and Password and can create your own Identity. In this function you will return a list of IAuthorization policies to be evaluated. I created my own authorization Policy and passed my new identity to it, so as to set the Identity in context.

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 中覆盖安全性:

So this example shows how you can override Security in WCF:

现在你的问题:

1.) 实施此技术并在您的身份中设置用户名和密码.现在,当您呼叫子服务时,从中获取身份提取用户名和密码并传递给子服务.

1.) Implement this Technique and Set UserName and Password in your identity. Now when ever you have call child service, get Identity extract Username and password from it and pass on to child service.

2.) 验证用户名和密码并为其生成一个令牌(应该为此创建一个新的令牌服务).将此令牌与用户名一起保存在您的身份中,并将这两个传递给您的子服务.现在要使这种方法起作用,子服务必须验证您新生成的令牌,为此您应该有一个令牌服务,它可以通过验证用户名和密码来创建令牌,并且还可以验证令牌和用户名.

2.) Authenticate UserName and Password and generate a token for that (should create a new token service for that). Save this Token in your Identity along with Username and pass these two to your child services. Now for this approach to work, child service has to validate your new generated token, for which you should have a token Service which can create token by validating username and password and also which can validate token along with username.

我个人会采用方法 2,但它会引入新的开销.

Personally I would go for approach 2, but it will introduce new overheads.

这篇关于如何将 WCF UserName clientCredentialType 传递给其他服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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