2014-01-15 28 views
3

我使用Authenticate方法從Microsoft.Xrm.Sdk.Client.IServiceManagement驗證CRM用戶。
此方法返回 System.IdentityModel.Tokens.GenericXmlSecurityToken,我需要返回作爲WebService響應(JSON或XML格式)。序列化/反序列化GenericXmlSecurityToken和安全 - CRM驗證

計劃是讓WebService客戶端在隨後的請求中傳遞此令牌。
我的問題是,我無法構造標記回來...

我的理解是,我需要TokenXmlProofTokenInternalTokenReference來構建可用於驗證有效GenericXmlSecurityToken

我的問題:

  • 我可以發送ProofTokenInternalTokenReference回到WebService的客戶,是否安全?我可以easliy返回TokenXML,ProofToken和InternalTokenReference,但我不知道它是否安全...
  • 如果上面的答案是沒有,是否有任何其他方式序列化/反序列化這種類型的令牌,所以它可以傳回客戶端?

在此先感謝您的幫助!
問候

回答

0

我已經解決我的問題 - 對於任何有興趣的解決方案的信息:
我最初的做法是不正確的,是過於複雜。事實上它非常簡單。

Authenticate方法返回AuthenticationCredentials從中我們可以得到SecurityTokenResponse.Response這是類型Microsoft.IdentityModel.Protocols.WSTrust.RequestSecurityTokenResponse

該對象可以分別使用WSTrust13ResponseSerializerWriteXml/ReadXml方法輕鬆地序列化/反序列化。

這解決了我的問題,我現在可以序列化令牌,將它們傳遞給客戶端並讀回每個請求。

+1

請你能提供一個代碼示例,謝謝 – Zinov

2

以下代碼不保證是未來的證明,但適用於當前使用的Dynamics CRM版本(2011,2013和2015)。從2015年開始,支持OAuth似乎是通過線路傳遞令牌的更好方式。

轉換一個SecurityTokenResponse爲Base64編碼的字符串:

public static string Serialize(SecurityTokenResponse securityTokenResponse) 
    { 
     XmlWriterSettings xmlWriterSettings = new XmlWriterSettings(); 
     xmlWriterSettings.Encoding = Encoding.UTF8; 

     using (MemoryStream memoryStream = new MemoryStream()) 
     using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings)) 
     { 
      WSTrust13ResponseSerializer serializer = new WSTrust13ResponseSerializer(); 
      WSTrustSerializationContext context = new WSTrustSerializationContext(); 
      serializer.WriteXml(securityTokenResponse.Response, xmlWriter, context); 
      xmlWriter.Flush(); 

      return Convert.ToBase64String(memoryStream.ToArray()); 
     } 
    } 

轉換Base64編碼字符串返回到SecurityTokenResponse

public static SecurityTokenResponse ParseToken(string serializedToken) 
    { 
     RequestSecurityTokenResponse response; 
     using (MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(serializedToken))) 
     using (XmlReader xmlReader = XmlReader.Create(memoryStream)) 
     { 
      WSTrust13ResponseSerializer serializer = new WSTrust13ResponseSerializer(); 
      WSTrustSerializationContext serializationContext = new WSTrustSerializationContext(); 
      response = serializer.ReadXml(xmlReader, serializationContext); 
     } 

     SecurityToken proofKey = new BinarySecretSecurityToken(response.RequestedProofToken.ProtectedKey.GetKeyBytes()); 
     DateTime? created = null; 
     DateTime? expires = null; 
     if (response.Lifetime != null) 
     { 
      created = response.Lifetime.Created; 
      expires = response.Lifetime.Expires; 
     } 
     if (!created.HasValue) 
     { 
      throw new Exception("Created unspecified"); 
     } 
     if (!expires.HasValue) 
     { 
      throw new Exception("Expires unspecified"); 
     } 

     SecurityToken securityToken = new GenericXmlSecurityToken(
       response.RequestedSecurityToken.SecurityTokenXml, 
       proofKey, 
       created.Value, 
       expires.Value, 
       response.RequestedAttachedReference, 
       response.RequestedUnattachedReference, 
       new ReadOnlyCollection<IAuthorizationPolicy>(new List<IAuthorizationPolicy>()) 
      ); 

     return new SecurityTokenResponse() 
     { 
      Response = response, 
      Token = securityToken 
     }; 
    } 

之所以選擇Base64編碼的編碼是因爲我送XML Web服務中的令牌。這消除了XML轉義XML字符串的需要。這可能會導致很多轉義:&gt;&lt;,&amp;等。如果您未通過XML Web服務發送序列化標記,則可能需要使用更易讀的編碼,如UTF8