我正在尝试实现身份验证/授权过程,该过程将在用户登录时生成JWT并将其放置在cookie中(在实现过程中,我主要使用本文-认为它适用于.NET Core,而我使用的是.NET 4.6:https://stormpath.com/blog/token-authentication-asp-net-core)。到目前为止,此过程可以正常进行,但是当我尝试通过Cookie中的JWT向安全端点(用[Authorize]属性装饰)发出请求时,总是收到401未经授权的响应。即使JWT接缝得到验证,并且CustomJwtDataFormat类的Unprotect方法也返回了AuthenticationTicket。
根据对这个问题的回答Why is my ClaimsIdentity IsAuthenticated always false (for web api Authorize filter)?中的建议 我在创建ClaimsIdentity时添加了AuthenticationType参数。但仍然是相同的401响应。
这是我的ConfigureAuth方法:
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
Provider = new CookieAuthenticationProvider(),
CookieName = "access_token",
AuthenticationMode =
Microsoft.Owin.Security.AuthenticationMode.Active,
AuthenticationType = AuthenticationTypes.Password,
TicketDataFormat = new CustomJwtDataFormat(
SecurityAlgorithms.HmacSha256,
SettingsConfig.TokenValidationParameters)
});
}
CustomJwtDataFormat类的Unprotect方法:
public AuthenticationTicket Unprotect(string protectedText)
{
var handler = new JwtSecurityTokenHandler();
ClaimsPrincipal principal = null;
SecurityToken validToken = null;
try
{
principal = handler.ValidateToken(protectedText, this.validationParameters, out validToken);
var validJwt = validToken as JwtSecurityToken;
if (validJwt == null)
{
throw new ArgumentException("Invalid JWT");
}
if (!validJwt.Header.Alg.Equals(algorithm, StringComparison.Ordinal))
{
throw new ArgumentException($"Algorithm must be '{algorithm}'");
}
}
catch (SecurityTokenValidationException e)
{
var ex = e;
return null;
}
catch (ArgumentException e)
{
var ex = e;
return null;
}
var identity = new ClaimsIdentity(principal.Identities.FirstOrDefault().Claims, AuthenticationTypes.Password);
// Validation passed. Return a valid AuthenticationTicket:
var authTicket = new AuthenticationTicket(identity, new AuthenticationProperties());
return authTicket;
我的TokenValidationParameters
public static TokenValidationParameters TokenValidationParameters = new TokenValidationParameters
{
// The signing key must match!
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
// Validate the JWT Issuer (iss) claim
ValidateIssuer = true,
ValidIssuer = "ExampleIssuer",
// Validate the JWT Audience (aud) claim
ValidateAudience = true,
ValidAudience = "ExampleAudience",
// Validate the token expiry
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(5)
};
GenerateToken方法:
public static string GenerateToken(MetadataForToken tokenContentAndMetadata)
{
var symmetricKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(tokenContentAndMetadata.SecretKey));
var tokenHandler = new JwtSecurityTokenHandler();
var now = DateTime.UtcNow;
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(tokenContentAndMetadata.Claims),
Expires = now.AddMinutes(Convert.ToInt32(tokenContentAndMetadata.ExpireMinutes)),
SigningCredentials = new SigningCredentials(symmetricKey, tokenContentAndMetadata.SecurityAlgorithm),
Issuer = "ExampleIssuer",
Audience = "ExampleAudience"
};
var sToken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(sToken);
return token;
}
我在做什么错了?