【问题标题】:OAuth and WCF SOAP serviceOAuth 和 WCF SOAP 服务
【发布时间】:2015-03-04 04:29:49
【问题描述】:

我正在尝试为 WCF SOAP 服务实现 OAuth 安全性。我可以在网上找到有关 OAUTH 和 REST 服务的示例。有没有将 OAuth 与 WCF SOAP 服务一起使用的最佳方法。如果可以使用 OAUth 保护 WCF SOAP,我还想知道在这种情况下是否可以使用基于声明的授权。

【问题讨论】:

  • OAuth 真的是为最终用户设计的。中间总是有一个 web 视图,所以一个真正的人(或者像一个真正的机器人一样的东西......)可以接受或拒绝身份验证过程。所以它并不适合机器到机器的转换。你应该更多地解释你想做什么,并指出你尝试过的例子或事情。

标签: wcf soap oauth-2.0


【解决方案1】:

简短的回答很简单,是的,您可以这样做。我试图找到一种“官方”的方式来做到这一点,但我没有成功,主要是因为 OAuth 并不是真正为这种情况设计的,稍后会详细介绍。首先虽然如何实际做到这一点。一种方法是提供自定义 ServiceAuthorizationManager 并在其中执行类似的操作

public class OAuthAuthorizationManager : ServiceAuthorizationManager
{
    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        // Extract the action URI from the OperationContext. Match this against the claims 
        // in the AuthorizationContext. 
        string action = operationContext.RequestContext.RequestMessage.Headers.Action;

        try
        {
            //get the message
            var message = operationContext.RequestContext.RequestMessage;

            //get the http headers
            var httpHeaders = ((System.ServiceModel.Channels.HttpRequestMessageProperty)message.Properties.Values.ElementAt(message.Properties.Keys.ToList().IndexOf("httpRequest"))).Headers;


            //get authorization header
            var authHeader = httpHeaders.GetValues("Authorization");

            if (authHeader != null)
            {
                var parts = authHeader[0].Split(' ');

                if (parts[0] == "Bearer")
                {
                    var tokenClaims = ValidateJwt(parts[1]);
                    foreach (System.Security.Claims.Claim c in tokenClaims.Where(c => c.Type == "http://www.contoso.com/claims/allowedoperation"))
                    {
                        var authorized = true;
                        //other claims authorization logic etc....
                        if(authorized)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;

        }
        catch (Exception)
        {
            throw;
        }

    }

    private static IEnumerable<System.Security.Claims.Claim> ValidateJwt(string jwt)
    {
        var handler = new JwtSecurityTokenHandler();
        var validationParameters = new TokenValidationParameters()
        {
            ValidAudience = "urn://your.audience",
            IssuerSigningKey = new InMemorySymmetricSecurityKey(Convert.FromBase64String("base64encoded symmetric key")),
            ValidIssuer = "urn://your.issuer",
            CertificateValidator = X509CertificateValidator.None,
            RequireExpirationTime = true
        };

        try
        {
            SecurityToken validatedToken;
            var principal = handler.ValidateToken(jwt, validationParameters, out validatedToken);
            
            return  principal.Claims;

        }
        catch (Exception e)
        {
            return new List<System.Security.Claims.Claim>();
        }

    }
}

请务必使用serviceAuthorizationElement 设置 web.config 以使用此自定义类

此示例还需要 System.IdentityModel.Tokens.Jwt nuget 包,但您的令牌可能是另一种格式,在这种情况下,您只需替换示例中的该逻辑即可。另外,请注意,此示例假设您将在 http 请求中的 Authorization 标头上传递我们的令牌,OAuth 2.0 Authorization Framework: Bearer Token Usage 文档还指定也可以使用表单编码的正文参数和 URI 查询参数。表单编码的正文参数方法可能与 SOAP 服务完全不兼容,但我认为您没有理由不修改此代码以在需要时也查看查询参数方法。

此代码的作用是针对您的服务的每个单个请求,CheckAccessCore 方法将触发,在它内部尝试提取和验证 JWT oauth 令牌,然后您可以使用提取的原则和相关声明来授权或拒绝对请求的授权.

综上所述,我认为最好的方法是根本不使用 OAuth,上述方法可行,但它是对 WCF SOAP 服务的保护方式的一种破解。 OAuth 也不意味着对用户进行身份验证,因此在将通过身份验证获得的不记名令牌传递给您的服务之前,您需要以其他方式执行此操作。如果您绝对必须使用 OAuth,您可以使用上述方法来帮助您入门,可能有更好的方法,但无论如何要使其工作和可读都不容易。如果您还没有查看过WS-Security,那么您应该这样做并熟悉为保护基于肥皂的服务而存在的大量信息和可能性,其中大部分在此处有大量示例。

【讨论】:

  • 需要安装其他 Nuget 包:“Microsoft.AspNetCore.Authentication.JwtBearer”、“Microsoft.Owin.Security.Cookies”、“Microsoft.Owin.Security.Jwt”
猜你喜欢
  • 1970-01-01
  • 2019-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-29
  • 1970-01-01
  • 1970-01-01
  • 2012-03-29
相关资源
最近更新 更多