0

我从 acs 获取令牌,如这篇文章Validating a SWT Token REST WCF Service中所述

但我无法提取 ACS 令牌。你能帮我吗?实际上,提取 acs 令牌“JsonNotifyRequestSecurityTokenResponse.FromJson”的类我无法得到它,因为提供的链接不起作用。

4

1 回答 1

0

我想你几个小时前在我的问题上发布了这个问题作为答案,然后将其删除。所以我查找了我的旧项目并找到了您需要的代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Policy;
using System.IdentityModel.Tokens;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Web;
using System.Xml.Linq;
using Thinktecture.IdentityModel.Extensions;

namespace Security {
    [DataContract]
    public class JsonNotifyRequestSecurityTokenResponse {
        [DataMember(Name = "appliesTo", Order = 1)]
        public string AppliesTo { get; set; }

        [DataMember(Name = "context", Order = 2)]
        public string Context { get; set; }

        [DataMember(Name = "created", Order = 3)]
        public string Created { get; set; }

        [DataMember(Name = "expires", Order = 4)]
        public string Expires { get; set; }

        [DataMember(Name = "securityToken", Order = 5)]
        public string SecurityTokenString { get; set; }

        [DataMember(Name = "tokenType", Order = 6)]
        public string TokenType { get; set; }

        public DateTime ValidFrom { get; set; }
        public DateTime ValidTo { get; set; }
        public GenericXmlSecurityToken SecurityToken { get; set; }

        public static JsonNotifyRequestSecurityTokenResponse FromJson(string jsonString) {
            JsonNotifyRequestSecurityTokenResponse rstr;

            var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(jsonString));
            var serializer = new DataContractJsonSerializer(typeof(JsonNotifyRequestSecurityTokenResponse));

            rstr = serializer.ReadObject(memoryStream) as JsonNotifyRequestSecurityTokenResponse;
            memoryStream.Close();

            ParseValues(rstr);
            return rstr;
        }

        private static void ParseValues(JsonNotifyRequestSecurityTokenResponse rstr) {
            rstr.ValidFrom = ulong.Parse(rstr.Created).ToDateTimeFromEpoch();
            rstr.ValidTo = ulong.Parse(rstr.Expires).ToDateTimeFromEpoch();
            rstr.SecurityTokenString = HttpUtility.HtmlDecode(rstr.SecurityTokenString);
            var xml = XElement.Parse(rstr.SecurityTokenString);

            string idAttribute = "";
            string tokenType = "";

            switch (rstr.TokenType) {
                case SecurityTokenTypes.Saml11:
                    idAttribute = "AssertionID";
                    tokenType = SecurityTokenTypes.Saml11;
                    break;
                case SecurityTokenTypes.Saml2:
                    idAttribute = "ID";
                    tokenType = SecurityTokenTypes.Saml2;
                    break;
                case SecurityTokenTypes.SWT:
                    idAttribute = "Id";
                    tokenType = SecurityTokenTypes.SWT;
                    break;
            }

            if (tokenType == SecurityTokenTypes.Saml11 || tokenType == SecurityTokenTypes.Saml2) {
                var tokenId = xml.Attribute(idAttribute);
                var xmlElement = xml.ToXmlElement();
                SecurityKeyIdentifierClause clause = null;

                if (tokenId != null) {
                    clause = new SamlAssertionKeyIdentifierClause(tokenId.Value);
                }

                rstr.SecurityToken = new GenericXmlSecurityToken(
                     xmlElement,
                     null,
                     rstr.ValidFrom,
                     rstr.ValidTo,
                     clause,
                     clause,
                     new ReadOnlyCollection<IAuthorizationPolicy>(new List<IAuthorizationPolicy>()));
            }
        }

        private class SecurityTokenTypes {
            public const string Saml2 = "urn:oasis:names:tc:SAML:2.0:assertion";
            public const string Saml11 = "urn:oasis:names:tc:SAML:1.0:assertion";
            public const string SWT = "http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0";
        }
    }
}

您应该Thinktecture.IdentityModel.Extensions从以下网址获取程序集:http: //identitymodel.codeplex.com/

我希望这有帮助。

编辑 - SWT 令牌处理

我不知道它是否有帮助,但我找到了一个SWTModule应该处理 SWT 令牌的方法。

public class SWTModule : IHttpModule {

    void IHttpModule.Dispose() {

    }

    void IHttpModule.Init(HttpApplication context) {
        context.BeginRequest += new EventHandler(context_BeginRequest);
    }

    void context_BeginRequest(object sender, EventArgs e) {
        //HANDLE SWT TOKEN VALIDATION
        // get the authorization header
        string headerValue = HttpContext.Current.Request.Headers.Get("Authorization");

        // check that a value is there
        if (string.IsNullOrEmpty(headerValue)) {
            throw new ApplicationException("unauthorized");
        }

        // check that it starts with 'WRAP'
        if (!headerValue.StartsWith("WRAP ")) {
            throw new ApplicationException("unauthorized");
        }

        string[] nameValuePair = headerValue.Substring("WRAP ".Length).Split(new char[] { '=' }, 2);

        if (nameValuePair.Length != 2 ||
             nameValuePair[0] != "access_token" ||
             !nameValuePair[1].StartsWith("\"") ||
             !nameValuePair[1].EndsWith("\"")) {
            throw new ApplicationException("unauthorized");
        }

        // trim off the leading and trailing double-quotes
        string token = nameValuePair[1].Substring(1, nameValuePair[1].Length - 2);

        // create a token validator
        TokenValidator validator = new TokenValidator(
             this.acsHostName,
             this.serviceNamespace,
             this.trustedAudience,
             this.trustedTokenPolicyKey);

        // validate the token
        if (!validator.Validate(token)) {
            throw new ApplicationException("unauthorized");
        }

    }
}

你还需要TokenValidator

public class TokenValidator {
    private string issuerLabel = "Issuer";
    private string expiresLabel = "ExpiresOn";
    private string audienceLabel = "Audience";
    private string hmacSHA256Label = "HMACSHA256";

    private string acsHostName;

    private string trustedSigningKey;
    private string trustedTokenIssuer;
    private string trustedAudienceValue;

    public TokenValidator(string acsHostName, string serviceNamespace, string trustedAudienceValue, string trustedSigningKey) {
        this.trustedSigningKey = trustedSigningKey;
        this.trustedTokenIssuer = String.Format("https://{0}.{1}/",
             serviceNamespace.ToLowerInvariant(),
             acsHostName.ToLowerInvariant());

        this.trustedAudienceValue = trustedAudienceValue;
    }

    public bool Validate(string token) {
        if (!this.IsHMACValid(token, Convert.FromBase64String(this.trustedSigningKey))) {
            return false;
        }

        if (this.IsExpired(token)) {
            return false;
        }

        if (!this.IsIssuerTrusted(token)) {
            return false;
        }

        if (!this.IsAudienceTrusted(token)) {
            return false;
        }

        return true;
    }

    public Dictionary<string, string> GetNameValues(string token) {
        if (string.IsNullOrEmpty(token)) {
            throw new ArgumentException();
        }

        return
             token
             .Split('&')
             .Aggregate(
             new Dictionary<string, string>(),
             (dict, rawNameValue) => {
                 if (rawNameValue == string.Empty) {
                     return dict;
                 }

                 string[] nameValue = rawNameValue.Split('=');

                 if (nameValue.Length != 2) {
                     throw new ArgumentException("Invalid formEncodedstring - contains a name/value pair missing an = character");
                 }

                 if (dict.ContainsKey(nameValue[0]) == true) {
                     throw new ArgumentException("Repeated name/value pair in form");
                 }

                 dict.Add(HttpUtility.UrlDecode(nameValue[0]), HttpUtility.UrlDecode(nameValue[1]));
                 return dict;
             });
    }

    private static ulong GenerateTimeStamp() {
        // Default implementation of epoch time
        TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
        return Convert.ToUInt64(ts.TotalSeconds);
    }

    private bool IsAudienceTrusted(string token) {
        Dictionary<string, string> tokenValues = this.GetNameValues(token);

        string audienceValue;

        tokenValues.TryGetValue(this.audienceLabel, out audienceValue);

        if (!string.IsNullOrEmpty(audienceValue)) {
            if (audienceValue.Equals(this.trustedAudienceValue, StringComparison.Ordinal)) {
                return true;
            }
        }

        return false;
    }

    private bool IsIssuerTrusted(string token) {
        Dictionary<string, string> tokenValues = this.GetNameValues(token);

        string issuerName;

        tokenValues.TryGetValue(this.issuerLabel, out issuerName);

        if (!string.IsNullOrEmpty(issuerName)) {
            if (issuerName.Equals(this.trustedTokenIssuer)) {
                return true;
            }
        }

        return false;
    }

    private bool IsHMACValid(string swt, byte[] sha256HMACKey) {
        string[] swtWithSignature = swt.Split(new string[] { "&" + this.hmacSHA256Label + "=" }, StringSplitOptions.None);

        if ((swtWithSignature == null) || (swtWithSignature.Length != 2)) {
            return false;
        }

        HMACSHA256 hmac = new HMACSHA256(sha256HMACKey);

        byte[] locallyGeneratedSignatureInBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(swtWithSignature[0]));

        string locallyGeneratedSignature = HttpUtility.UrlEncode(Convert.ToBase64String(locallyGeneratedSignatureInBytes));

        return locallyGeneratedSignature == swtWithSignature[1];
    }

    private bool IsExpired(string swt) {
        try {
            Dictionary<string, string> nameValues = this.GetNameValues(swt);
            string expiresOnValue = nameValues[this.expiresLabel];
            ulong expiresOn = Convert.ToUInt64(expiresOnValue);
            ulong currentTime = Convert.ToUInt64(GenerateTimeStamp());

            if (currentTime > expiresOn) {
                return true;
            }

            return false;
        } catch (KeyNotFoundException) {
            throw new ArgumentException();
        }
    }
}
于 2012-04-09T11:45:39.367 回答