Thinktecture BasicAuthenticationSecurityTokenHandler 返回 StatusCode 500,内部服务器错误
Thinktecture BasicAuthenticationSecurityTokenHandler returning StatusCode 500, Internal Server Error
我最近从旧的 Thinktecture IdentityModel 升级到最新的支持 Web 的 IdentityModel API 2.
当我使用 System.Web.Mvc v5.2.2.0 时,下面的代码适用于以前的 nuget 包(以及托管它的较小的 webapi 版本),尽管它到达了 ValidateToken 函数的末尾,但错误是调用客户端收到 {StatusCode: 500, ReasonPhrase: 'Internal Server Error'
public class BasicAuthSecurityTokenHandlerWithClaimsOutput : BasicAuthenticationSecurityTokenHandler
{
public BasicAuthSecurityTokenHandlerWithClaimsOutput(ValidateNameWithClaims validateNameGetClaims)
: base()
{
if (validateNameGetClaims == null)
{
throw new ArgumentNullException("ValidateNameGetClaims");
}
this.validateNameGetClaims = validateNameGetClaims;
}
protected readonly ValidateNameWithClaims validateNameGetClaims;
public override ReadOnlyCollection<ClaimsIdentity> ValidateToken(SecurityToken token)
{
if (token == null)
{
throw new ArgumentNullException("token");
}
if (base.Configuration == null)
{
throw new InvalidOperationException("No Configuration set");
}
UserNameSecurityToken unToken = token as UserNameSecurityToken;
if (unToken == null)
{
throw new ArgumentException("SecurityToken is not a UserNameSecurityToken");
}
Claim[] lookedUpClaims = null;
try
{
if (this.validateNameGetClaims(unToken.UserName, unToken.Password, out lookedUpClaims) == false)
{
throw new SecurityTokenValidationException(unToken.UserName);
}
}
catch (Exception e)
{
// log the exception
throw new SecurityTokenValidationException(unToken.UserName);
}
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, unToken.UserName),
new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.Password),
AuthenticationInstantClaim.Now
};
if(lookedUpClaims != null && lookedUpClaims.Length > 0)
claims.AddRange(lookedUpClaims);
if (RetainPassword)
{
claims.Add(new Claim("password", unToken.Password));
}
var identity = new ClaimsIdentity(claims, "Basic");
if (Configuration.SaveBootstrapContext)
{
if (this.RetainPassword)
{
identity.BootstrapContext = new BootstrapContext(unToken, this);
}
else
{
var bootstrapToken = new UserNameSecurityToken(unToken.UserName, null);
identity.BootstrapContext = new BootstrapContext(bootstrapToken, this);
}
}
return new List<ClaimsIdentity> { identity }.AsReadOnly();
}
}
我要退回的声明是:
[0] = {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: user@username.com}
[1] {http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod: http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password}
[2] {http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant: 2015-01-27T00:50:20.603Z}
[3] {fuid: 6}
[4] {fustate: FL}
我配置:
public static class BasicAuthHandlerExtensionWithClaimsOutput
{
public static void AddBasicAuthenticationWithClaimsOutput(
this AuthenticationConfiguration configuration,
ValidateNameWithClaims validationDelegate,
string realm = "localhost", bool retainPassword = false)
{
var handler = new BasicAuthSecurityTokenHandlerWithClaimsOutput(validationDelegate)
{
RetainPassword = retainPassword
};
configuration.AddMapping(new AuthenticationOptionMapping
{
TokenHandler = new SecurityTokenHandlerCollection { handler },
Options = AuthenticationOptions.ForAuthorizationHeader(scheme: "Basic"),
Scheme = AuthenticationScheme.SchemeAndRealm("Basic", realm)
});
}
}
var authConfig = new AuthenticationConfiguration
{
EnableSessionToken = true,
SendWwwAuthenticateResponseHeaders = true,
RequireSsl = false,
SessionToken = new SessionTokenConfiguration
{
Audience = "http://audience.com,
IssuerName = "http://issuer.com",
EndpointAddress = appSettings.TokenEndPoint,
SigningKey = appSettings.StsSigningKey,
DefaultTokenLifetime = new TimeSpan(1, 0, 0)
}
};
var userCredentialsService = new CredentialsService(credentialStore);
authConfig.AddBasicAuthenticationWithClaimsOutput(userCredentialsService.Validate);
config.MessageHandlers.Add(new AuthenticationHandler(authConfig));
知道我做错了什么吗?
使用 Fiddler,你会发现 Method not found: no match for ctor signature
然后稍微搜索一下就会发现 this comment 是 IdentityModel 的作者。
所需的签名存在于 System.IdentityModel.Tokens.Jwt 的 2.0.0.0 版本中,但不再存在于版本 4.0.20622.1351
中
你必须使用武士刀。
我最近从旧的 Thinktecture IdentityModel 升级到最新的支持 Web 的 IdentityModel API 2.
当我使用 System.Web.Mvc v5.2.2.0 时,下面的代码适用于以前的 nuget 包(以及托管它的较小的 webapi 版本),尽管它到达了 ValidateToken 函数的末尾,但错误是调用客户端收到 {StatusCode: 500, ReasonPhrase: 'Internal Server Error'
public class BasicAuthSecurityTokenHandlerWithClaimsOutput : BasicAuthenticationSecurityTokenHandler
{
public BasicAuthSecurityTokenHandlerWithClaimsOutput(ValidateNameWithClaims validateNameGetClaims)
: base()
{
if (validateNameGetClaims == null)
{
throw new ArgumentNullException("ValidateNameGetClaims");
}
this.validateNameGetClaims = validateNameGetClaims;
}
protected readonly ValidateNameWithClaims validateNameGetClaims;
public override ReadOnlyCollection<ClaimsIdentity> ValidateToken(SecurityToken token)
{
if (token == null)
{
throw new ArgumentNullException("token");
}
if (base.Configuration == null)
{
throw new InvalidOperationException("No Configuration set");
}
UserNameSecurityToken unToken = token as UserNameSecurityToken;
if (unToken == null)
{
throw new ArgumentException("SecurityToken is not a UserNameSecurityToken");
}
Claim[] lookedUpClaims = null;
try
{
if (this.validateNameGetClaims(unToken.UserName, unToken.Password, out lookedUpClaims) == false)
{
throw new SecurityTokenValidationException(unToken.UserName);
}
}
catch (Exception e)
{
// log the exception
throw new SecurityTokenValidationException(unToken.UserName);
}
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, unToken.UserName),
new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.Password),
AuthenticationInstantClaim.Now
};
if(lookedUpClaims != null && lookedUpClaims.Length > 0)
claims.AddRange(lookedUpClaims);
if (RetainPassword)
{
claims.Add(new Claim("password", unToken.Password));
}
var identity = new ClaimsIdentity(claims, "Basic");
if (Configuration.SaveBootstrapContext)
{
if (this.RetainPassword)
{
identity.BootstrapContext = new BootstrapContext(unToken, this);
}
else
{
var bootstrapToken = new UserNameSecurityToken(unToken.UserName, null);
identity.BootstrapContext = new BootstrapContext(bootstrapToken, this);
}
}
return new List<ClaimsIdentity> { identity }.AsReadOnly();
}
}
我要退回的声明是:
[0] = {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: user@username.com}
[1] {http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod: http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password}
[2] {http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant: 2015-01-27T00:50:20.603Z}
[3] {fuid: 6}
[4] {fustate: FL}
我配置:
public static class BasicAuthHandlerExtensionWithClaimsOutput
{
public static void AddBasicAuthenticationWithClaimsOutput(
this AuthenticationConfiguration configuration,
ValidateNameWithClaims validationDelegate,
string realm = "localhost", bool retainPassword = false)
{
var handler = new BasicAuthSecurityTokenHandlerWithClaimsOutput(validationDelegate)
{
RetainPassword = retainPassword
};
configuration.AddMapping(new AuthenticationOptionMapping
{
TokenHandler = new SecurityTokenHandlerCollection { handler },
Options = AuthenticationOptions.ForAuthorizationHeader(scheme: "Basic"),
Scheme = AuthenticationScheme.SchemeAndRealm("Basic", realm)
});
}
}
var authConfig = new AuthenticationConfiguration
{
EnableSessionToken = true,
SendWwwAuthenticateResponseHeaders = true,
RequireSsl = false,
SessionToken = new SessionTokenConfiguration
{
Audience = "http://audience.com,
IssuerName = "http://issuer.com",
EndpointAddress = appSettings.TokenEndPoint,
SigningKey = appSettings.StsSigningKey,
DefaultTokenLifetime = new TimeSpan(1, 0, 0)
}
};
var userCredentialsService = new CredentialsService(credentialStore);
authConfig.AddBasicAuthenticationWithClaimsOutput(userCredentialsService.Validate);
config.MessageHandlers.Add(new AuthenticationHandler(authConfig));
知道我做错了什么吗?
使用 Fiddler,你会发现 Method not found: no match for ctor signature
然后稍微搜索一下就会发现 this comment 是 IdentityModel 的作者。
所需的签名存在于 System.IdentityModel.Tokens.Jwt 的 2.0.0.0 版本中,但不再存在于版本 4.0.20622.1351
中你必须使用武士刀。