OAuth 和 WCF SOAP 服务
OAuth and WCF SOAP service
我正在尝试为 WCF SOAP 服务实现 OAuth 安全性。我可以在网上找到关于 OAUTH 和 REST 服务的示例。是否有将 OAuth 与 WCF SOAP 服务一起使用的最佳方法。如果可以使用 OAUth 保护 WCF SOAP,我还想知道在这种情况下我是否可以使用基于声明的授权。
简短的回答很简单,是的,你可以做到。我试图找到一种“官方”方式来做到这一点,但没有成功,主要是因为 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 以使用此自定义 class 使用 serviceAuthorizationElement
此示例也需要 System.IdentityModel.Tokens.Jwt nuget 包,但您的令牌可能采用另一种格式,在这种情况下,您只需替换示例中的逻辑即可。另外,请注意,此示例假设您将在 http 请求中的授权 header 上传递我们的令牌,OAuth 2.0 Authorization Framework: Bearer Token Usage 文档还指定表单编码 body 参数和 URI 查询参数也可以使用。表单编码的 body 参数方法可能与 SOAP 服务完全不兼容,但我认为您没有理由不调整此代码以在需要时也查看查询参数方法。
此代码的作用是针对您服务的每个请求,CheckAccessCore 方法都会触发,在它内部尝试提取和验证 JWT oauth 令牌,然后您可以使用提取的原则和相关声明来授权或拒绝授权请求。
综上所述,我认为最好的方法是根本不使用 OAuth,上面的方法有效,但它是对 WCF SOAP 服务的安全保护方式的破解。 OAuth 也不意味着对用户进行身份验证,因此在将通过身份验证获得的不记名令牌传递到您的服务之前,您需要以其他方式执行此操作。如果你绝对必须使用 OAuth,你可以使用上面的方法来开始,可能有更好的方法,但要让它工作和可读无论如何都不容易。如果您还没有研究过 WS-Security,您应该研究一下,并熟悉为保护基于 soap 的服务而存在的大量信息和可能性,其中大部分在此处都有大量示例。
我正在尝试为 WCF SOAP 服务实现 OAuth 安全性。我可以在网上找到关于 OAUTH 和 REST 服务的示例。是否有将 OAuth 与 WCF SOAP 服务一起使用的最佳方法。如果可以使用 OAUth 保护 WCF SOAP,我还想知道在这种情况下我是否可以使用基于声明的授权。
简短的回答很简单,是的,你可以做到。我试图找到一种“官方”方式来做到这一点,但没有成功,主要是因为 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 以使用此自定义 class 使用 serviceAuthorizationElement
此示例也需要 System.IdentityModel.Tokens.Jwt nuget 包,但您的令牌可能采用另一种格式,在这种情况下,您只需替换示例中的逻辑即可。另外,请注意,此示例假设您将在 http 请求中的授权 header 上传递我们的令牌,OAuth 2.0 Authorization Framework: Bearer Token Usage 文档还指定表单编码 body 参数和 URI 查询参数也可以使用。表单编码的 body 参数方法可能与 SOAP 服务完全不兼容,但我认为您没有理由不调整此代码以在需要时也查看查询参数方法。
此代码的作用是针对您服务的每个请求,CheckAccessCore 方法都会触发,在它内部尝试提取和验证 JWT oauth 令牌,然后您可以使用提取的原则和相关声明来授权或拒绝授权请求。
综上所述,我认为最好的方法是根本不使用 OAuth,上面的方法有效,但它是对 WCF SOAP 服务的安全保护方式的破解。 OAuth 也不意味着对用户进行身份验证,因此在将通过身份验证获得的不记名令牌传递到您的服务之前,您需要以其他方式执行此操作。如果你绝对必须使用 OAuth,你可以使用上面的方法来开始,可能有更好的方法,但要让它工作和可读无论如何都不容易。如果您还没有研究过 WS-Security,您应该研究一下,并熟悉为保护基于 soap 的服务而存在的大量信息和可能性,其中大部分在此处都有大量示例。