OAuth 和 WCF SOAP 服务 [英] OAuth and WCF SOAP service

查看:55
本文介绍了OAuth 和 WCF SOAP 服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to implement OAuth security for a WCF SOAP service. I could find samples online which talks about OAUTH and REST service. Is there any best approach to use OAuth with WCF SOAP service. If it is possible to secure WCF SOAP usig OAUth, I also would like to know whether I could use claims based authorization in this case.

推荐答案

简单的回答是肯定的,您可以这样做.我试图找到一种官方"的方法来做到这一点,但我没有成功,主要是因为 OAuth 并不是真正为这种情况设计的,稍后会详细介绍.首先虽然如何实际做到这一点.一种方法是提供自定义 ServiceAuthorizationManager 并在它内部做这样的事情

The short answer is a simple yes, you can do this. I tried to find an "official" way to do this and I was not successful, mostly because OAuth is not really designed for this scenario, more on that later. First though how to actually do it. One way to do it would be to provide a custom ServiceAuthorizationManager and inside of it do something like this

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

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

This example requires the System.IdentityModel.Tokens.Jwt nuget package as well, your tokens might be in another format though and in that case you would need to just replace that logic in the example. Also, note that this example is assuming you will be passing our token on the Authorization header in the http request, the OAuth 2.0 Authorization Framework: Bearer Token Usage documentation also specifies that both form encoded body parameters and URI query paramters may be used as well. The form encoded body parameter method is probably entirely incompatible with SOAP services but I see no reason you could not adapt this code to also look at the query parameter method if needed.

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

What this code does is for every single request to your service the CheckAccessCore method will fire, inside it attempts to extract and validate the JWT oauth token then you can use the extracted principle and associated claims to authorize or deny authorization to the request.

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

All of this said, I think the best approach would be to not use OAuth at all, the above works but it is a hack to how WCF SOAP services are meant to be secured. OAuth is also not meant to authenticate the user, so you will need to do that in some other way prior to passing the bearer token obtained from authentication on to your service. If you absolutely must use OAuth you can use the above to get you started, there may be better ways but it is not easy by any measure to make it work and be readable. If you have not looked into WS-Security you should do that and familiarize yourself with the abundance of information and possibilities that exist for securing a soap based service most of which have numerous examples to go on here.

这篇关于OAuth 和 WCF SOAP 服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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