我从 acs 获取令牌,如这篇文章Validating a SWT Token REST WCF Service中所述
但我无法提取 ACS 令牌。你能帮我吗?实际上,提取 acs 令牌“JsonNotifyRequestSecurityTokenResponse.FromJson”的类我无法得到它,因为提供的链接不起作用。
我从 acs 获取令牌,如这篇文章Validating a SWT Token REST WCF Service中所述
但我无法提取 ACS 令牌。你能帮我吗?实际上,提取 acs 令牌“JsonNotifyRequestSecurityTokenResponse.FromJson”的类我无法得到它,因为提供的链接不起作用。
我想你几个小时前在我的问题上发布了这个问题作为答案,然后将其删除。所以我查找了我的旧项目并找到了您需要的代码:
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();
}
}
}