【发布时间】:2017-08-18 08:21:23
【问题描述】:
我的 JWT 令牌验证不起作用。
以下前 3 个代码块是 JWT 生成服务器。最后是我的资源服务器。两者都是 ASP.NET 服务器应用程序。 JWT 生成器正在生成代码,当我使用 Postman 在 Header Authentication 中发送该代码以访问安全([Authorized])WebAPI 时,我收到了未经授权的消息。我想我在配置两个应用程序时都犯了一些错误
启动类是
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
// Web API routes
config.MapHttpAttributeRoutes();
ConfigureOAuth(app);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth2/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat()
};
// OAuth 2.0 Bearer Access Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
}
}
CustomOAuthProvider
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
namespace AuthorizationServer.Api.Providers
{
public class CustomOAuthProvider : OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return Task.FromResult<object>(null);
}
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
if (context.UserName != context.Password)
{
context.SetError("invalid_grant", "The user name or password is incorrect");
//return;
return Task.FromResult<object>(null);
}
var identity = new ClaimsIdentity("JWT");
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, "Manager"));
identity.AddClaim(new Claim(ClaimTypes.Role, "Supervisor"));
var props = new AuthenticationProperties(new Dictionary<string, string>
{
{
"audience", "099153c2625149bc8ecb3e85e03f0022"
}
});
var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);
return Task.FromResult<object>(null);
}
}
}
自定义JWT格式
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler.Encoder;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Web;
using Thinktecture.IdentityModel.Tokens;
namespace AuthorizationServer.Api.Formats
{
public class CustomJwtFormat : ISecureDataFormat<AuthenticationTicket>
{
private readonly string _issuer = "http://jwtauthzsrv.azurewebsites.net";
public CustomJwtFormat()
{
}
public string Protect(AuthenticationTicket data)
{
if (data == null) {
throw new ArgumentNullException("data");
}
string symmetricKeyAsBase64 = "IxrAjDoa2FqElO7IhrSrUJELhUckePEPVpaePlS_Xaw";
var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
var signingKey = new HmacSigningCredentials(keyByteArray);
var issued = data.Properties.IssuedUtc;
var expires = data.Properties.ExpiresUtc;
var token = new JwtSecurityToken(_issuer, "099153c2625149bc8ecb3e85e03f0022", data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey);
var handler = new JwtSecurityTokenHandler();
var jwt = handler.WriteToken(token);
return jwt;
}
public AuthenticationTicket Unprotect(string protectedText)
{
throw new NotImplementedException();
}
}
}
现在这是我的资源启动代码
namespace ResourceServer.Api
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
ConfigureOAuth(app);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
var issuer = "http://jwtauthzsrv.azurewebsites.net";
var audience = "099153c2625149bc8ecb3e85e03f0022";
var secret = TextEncodings.Base64Url.Decode("IxrAjDoa2FqElO7IhrSrUJELhUckePEPVpaePlS_Xaw");
// Api controllers with an [Authorize] attribute will be validated with JWT
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audience },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
},
Provider = new OAuthBearerAuthenticationProvider
{
OnValidateIdentity = context =>
{
context.Ticket.Identity.AddClaim(new System.Security.Claims.Claim("newCustomClaim", "newValue"));
return Task.FromResult<object>(null);
}
}
});
}
}
}
【问题讨论】:
-
您能否也显示您向 Postman 提出的请求?
-
我选择后与URL localhost:18303/api/protected然后,在报头我把这个密钥值令牌从早期请求的授权承载eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6ImEiLCJzdWIiOiJhIiwicm9sZSI6WyJNYW5hZ2VyIiwiU3VwZXJ2aXNvciJdLCJpc3MiOiJodHRwOi8vand0YXV0aHpzcnYuYXp1cmV3ZWJzaXRlcy5uZXQiLCJhdWQiOiIwOTkxNTNjMjYyNTE0OWJjOGVjYjNlODVlMDNmMDAyMiIsImV4cCI6MTQ5MDQ0MDc2MCwibmJmIjoxNDkwNDM4OTYwfQ.DnC4Pn0vf1D3mlMlbskM8MXd_8_4JepX0La4GSeJMu0 B> 跨度>生成
-
如果你转到jwt.io,到调试器部分并尝试令牌,你会看到它标记它无效。所以,问题似乎出在生成令牌时。
-
我去了jwt.io并在底部的VERIFY SIGNATURE文本框中输入了“IxrAjDoa2FqElO7IhrSrUJELhUckePEPVpaePlS_Xaw”,然后单击复选框“secret base64 encoded”消息转为已验证
-
不知何故,jwt.io 上的前一个令牌没有提取“PAYLOAD:DATA”,但随后我生成了另一个令牌,然后有效负载开始显示在代码中发送的数据,该令牌是 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9。 eyJ1bmlxdWVfbmFtZSI6ImEiLCJzdWIiOiJhIiwicm9sZSI6WyJNYW5hZ2VyIiwiU3VwZXJ2aXNvciJdLCJpc3MiOiJodHRwOi8vd3d3Lm15d2Vic2l0ZS5jb20iLCJleHAiOjE0OTA0NDU4ODIsIm5iZiI6MTQ5MDQ0NDA4Mn0.WIv_B30y9o8bfLFnqotrGupoqHAGRNjnQzS47ZoBZxo 跨度>