OAuth和WCF SOAP服务

时间:2015-03-04 04:29:50

标签: wcf soap oauth-2.0

我正在尝试为WCF SOAP服务实现OAuth安全性。我可以在网上找到有关OAUTH和REST服务的样本。有没有最好的方法来使用OAuth与WCF SOAP服务。如果可以保证WCF SOAP usig OAUth,我也想知道在这种情况下我是否可以使用基于声明的授权。

1 个答案:

答案 0 :(得分:5)

简短的答案很简单,你可以这样做。我试图找到一个"官员"这样做的方式我并没有成功,主要是因为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>();
        }

    }
}

请务必将web.config设置为使用serviceAuthorizationElement

来使用此自定义类

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

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

所有这些都说,我认为最好的方法是根本不使用OAuth,上面的工作,但它是如何保护WCF SOAP服务的黑客。 OAuth也不用于对用户进行身份验证,因此在将从身份验证中获取的承载令牌传递到您的服务之前,您需要以其他方式执行此操作。如果你绝对必须使用OAuth,你可以使用上面的内容来开始,可能有更好的方法,但任何措施都不容易让它工作和可读。如果您没有查看WS-Security,那么您应该这样做,并熟悉丰富的信息和可能性,以确保基于肥皂的服务,其中大多数都有很多例子可以在这里进行。