c# - 指定的算法无效 - 自定义 STS

标签 c# asp.net sharepoint sts-securitytokenservice

我已经实现了一个自定义 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/

相关文章:

c# - "Token?"的确切定义是什么

c# - 如何强制浏览器使用版本控制重新加载缓存的静态文件?

sharepoint - 如何仅为具有特定模板 ID 的列表添加事件接收器

sharepoint - 为什么 SharePoint Designer 工作流在编辑后似乎没有在 SharePoint 网站上更新?

c# - 如何使用 DNX 和 ASP.NET 5 实现持续交付

c# - 命名复杂的方法

c# - 如何在 LINQ 中将匿名类型转换为强类型?

javascript - ListBoxFor为每个选项元素添加数据属性

c# - 在 ASP.NET Core 中,有没有办法从 Program.cs 设置中间件?

c# - ASP.NET 错误处理问题