我已经实现了一个自定义 STS,以便从我们的 Web 应用程序到托管在别处的 SharePoint 实例对用户进行身份验证,并显示在应用程序的框架中。
这在开发期间和测试期间都运行良好,但是在 UAT 期间间歇性地抛出以下异常:
[System.Security.Cryptography.CryptographicException] Invalid algorithm specified.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature)
at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash)
at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash)
at System.Security.Cryptography.RSAPKCS1SignatureFormatter.CreateSignature(Byte[] rgbHash)
at System.IdentityModel.SignedXml.ComputeSignature(HashAlgorithm hash, AsymmetricSignatureFormatter formatter, String signatureMethod)
at System.IdentityModel.SignedXml.ComputeSignature(SecurityKey signingKey)
at System.IdentityModel.EnvelopedSignatureWriter.ComputeSignature()
at System.IdentityModel.EnvelopedSignatureWriter.OnEndRootElement()
at System.IdentityModel.Tokens.SamlSecurityTokenHandler.WriteAssertion(XmlWriter writer, SamlAssertion assertion)
at System.IdentityModel.Tokens.SecurityTokenHandlerCollection.WriteToken(XmlWriter writer, SecurityToken token)
at System.IdentityModel.Protocols.WSTrust.WSTrustSerializationHelper.WriteRSTRXml(XmlWriter writer, String elementName, Object elementValue, WSTrustSerializationContext context, WSTrustConstantsAdapter trustConstants)
at System.IdentityModel.Protocols.WSTrust.WSTrustSerializationHelper.WriteKnownResponseElement(RequestSecurityTokenResponse rstr, XmlWriter writer, WSTrustSerializationContext context, WSTrustResponseSerializer responseSerializer, WSTrustConstantsAdapter trustConstants)
at System.IdentityModel.Protocols.WSTrust.WSTrust13ResponseSerializer.WriteKnownResponseElement(RequestSecurityTokenResponse rstr, XmlWriter writer, WSTrustSerializationContext context)
at System.IdentityModel.Protocols.WSTrust.WSTrustSerializationHelper.WriteResponse(RequestSecurityTokenResponse response, XmlWriter writer, WSTrustSerializationContext context, WSTrustResponseSerializer responseSerializer, WSTrustConstantsAdapter trustConstants)
at System.IdentityModel.Protocols.WSTrust.WSTrust13ResponseSerializer.WriteXml(RequestSecurityTokenResponse response, XmlWriter writer, WSTrustSerializationContext context)
at System.IdentityModel.Services.WSFederationSerializer.GetResponseAsString(RequestSecurityTokenResponse response, WSTrustSerializationContext context)
at System.IdentityModel.Services.SignInResponseMessage..ctor(Uri baseUrl, RequestSecurityTokenResponse response, WSFederationSerializer federationSerializer, WSTrustSerializationContext context)
at System.IdentityModel.Services.FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(SignInRequestMessage requestMessage, ClaimsPrincipal principal, SecurityTokenService sts, WSFederationSerializer federationSerializer)
at Web.Secure.SharePoint.ProcessRequest()
STS的实现如下:
using System.IdentityModel;
using System.IdentityModel.Configuration;
using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Tokens;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
namespace Core.Services
{
public class SharepointSecurityTokenService : SecurityTokenService
{
public SharepointSecurityTokenService(SecurityTokenServiceConfiguration securityTokenServiceConfiguration)
: base(securityTokenServiceConfiguration)
{
}
protected override Scope GetScope(ClaimsPrincipal principal, RequestSecurityToken request)
{
var scope = new Scope(request.AppliesTo.Uri.OriginalString, SecurityTokenServiceConfiguration.SigningCredentials);
scope.TokenEncryptionRequired = false;
scope.ReplyToAddress = request.ReplyTo;
return scope;
}
protected override ClaimsIdentity GetOutputClaimsIdentity(ClaimsPrincipal principal, RequestSecurityToken request, Scope scope)
{
var identity = new ClaimsIdentity(principal.Claims);
return identity;
}
}
}
调用它并生成响应表单的代码如下:
var identity = (ClaimsIdentity)HttpContext.Current.User.Identity;
identity.AddClaim(new Claim(ClaimTypes.Role, role));
var claimsPrinciple = new ClaimsPrincipal(identity);
var requestMessage = (SignInRequestMessage)WSFederationMessage.CreateFromNameValueCollection(sharePointLibraryUri, parameters);
var sharepointCertificate = Global.AppCache.GetSharepointCertificate();
if (sharepointCertificate == null)
{
throw new SharePointRequestException("No SharePoint signing certificate.", requestId);
}
var signingCredentials = new X509SigningCredentials(sharepointCertificate);
var config = new SecurityTokenServiceConfiguration(Settings.Default.SharePointTokenIssuerName, signingCredentials);
var sts = new SharepointSecurityTokenService(config);
var responseMessage = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(requestMessage, claimsPrinciple, sts);
var responseForm = responseMessage.WriteFormPost();
Response.Write(responseForm);
确认我们在所有环境中使用了相同的证书,并且它在开发中始终有效,但在服务器上失败。更令人困惑的是,它在这台服务器上一次工作了几个小时,但没有明显的原因会再次停止工作。我不知道是什么触发它开始或停止工作。
最佳答案
您可能缺少对算法的引用。您可能需要在应用程序启动时包含此行。
CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
关于c# - 指定的算法无效 - 自定义 STS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24455953/