ASP.NET Core 2.0 웹 API에서 JWT 토큰 생성이 작동하지만 이전에 생성 된 토큰과 동일한 만료 시간을 갖는 문제가 발생합니다. 사람.새 JWT 토큰이 이전 토큰과 만료 됨
예를 들어 로그인 자격 증명을 게시하고 액세스 토큰을 반환합니다. 액세스 토큰은 [Authorize] API 끝점에서 예상대로 작동합니다. 테스트 목적으로 1 분 후에 만료 토큰을 설정합니다. 1 분 후 토큰이 만기되고 인증 된 엔드 포인트는 예상대로 401을 리턴합니다.
저는 클라이언트 측 응용 프로그램에서 401을 처리하고 있습니다. 로그인 양식이 나타나고 사용자가 다시 로그인합니다. 새 토큰이 생성되어 리턴됩니다. 유일한 문제는이 새로운 토큰이 초기에 생성 된 토큰과 정확히 동일한 'ValidTo'DateTime을가집니다.이 토큰이 이미 만료되었으므로이 새 토큰을 사용하여 401을 반환 한 후 모든 호출이 발생합니다. 두 개의 다른 토큰이 사용되고 있음을 확인했습니다.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler : 정보 : 유효성을 검사하는 데 실패는 문제가되지 않습니다 그래서 내가 (예상 만료 된 토큰) 잘못된 토큰
첫 번째 토큰 실패를 통과하여, 확인 토큰 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZGFtQHBytNDRiYS1 ... Do1NzM5NS8ifQ.t8DjvlGV7GZ3xucwu-1hlJRXA5owPdP9t7kfYiiJHyQ.
Microsoft.IdentityModel.Tokens.SecurityTokenExpiredException : IDX10223 : 평생 유효성 검사가 실패했습니다. 토큰이 만료되었습니다.
ValidTo : '11// 2017 19시 23분 9초 08 '
현재 시간 : '11/08/2017 19시 23분 13초'. 정보 :
두 번째 토큰 실패
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler를 (이전의 표시로 ValidTo 같은 예상하지) 토큰 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZGFtQ ... dDo1NzM5NS8ifQ을 확인하지 못했습니다. 2TMPJvYnQl1Jw78M2nj40uD3qejBEciXfKC845saGNI.
Microsoft.IdentityModel.Tokens.SecurityTokenExpiredException : IDX10223 : 평생 유효성 검사가 실패했습니다. 토큰이 만료되었습니다.
ValidTo : '11// 2017 19시 23분 9초 08 '
현재 시간 : '11/08/2017 19시 23분 34초'. Startup.cs에
JWT 구성 토큰 생성
services.Configure<JwtIssuerOptions>(options => {
options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials(SigningKey, SecurityAlgorithms.HmacSha256);
options.ValidFor = TimeSpan.FromMinutes(1);
});
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],
ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],
ValidateIssuerSigningKey = true,
IssuerSigningKey = SigningKey,
RequireExpirationTime = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
};
});
로그인 작업 :
[HttpPost]
public async Task<IActionResult> Login([FromBody]CredentialsViewModel credentials)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var identity = await GetClaimsIdentity(credentials.UserName, credentials.Password);
if (identity == null)
{
return BadRequest(Errors.AddErrorToModelState("login_failure", "Invalid username or password.", ModelState));
}
// Serialize and return the response
var response = new
{
id = identity.Claims.Single(c => c.Type == "id").Value,
auth_token = await _jwtFactory.GenerateEncodedToken(credentials.UserName, identity),
expires_in = (int)_jwtOptions.ValidFor.TotalSeconds
};
var json = JsonConvert.SerializeObject(response, _serializerSettings);
return new OkObjectResult(json);
}
토큰이 생성되는
JwtFactory있어서
private readonly JwtIssuerOptions _jwtOptions;
public JwtFactory(IOptions<JwtIssuerOptions> jwtOptions)
{
_jwtOptions = jwtOptions.Value;
ThrowIfInvalidOptions(_jwtOptions);
}
public async Task<string> GenerateEncodedToken(string userName, ClaimsIdentity identity)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
identity.FindFirst("rol"),
identity.FindFirst("id")
};
// Create the JWT security token and encode it.
var jwt = new JwtSecurityToken(
issuer: _jwtOptions.Issuer,
audience: _jwtOptions.Audience,
claims: claims,
notBefore: _jwtOptions.NotBefore,
expires: _jwtOptions.Expiration,
signingCredentials: _jwtOptions.SigningCredentials);
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
return encodedJwt;
}
내 JwtIssuerOptions 모델에서 만료는 IssuedAt Datetime을 사용하고 ValidFor 시간 간격을 자동으로 추가하는 람다입니다. IssuedAt는 모델 선언에서 DateTime.UtcNow로 간단히 초기화됩니다. 제 경우에는 ValidFor 만 Startup에서 명시 적으로 설정해야합니다. JwtSecurityToken은 System.IdentityModel.Tokens.Jwt 내부의 클래스이며 만료하려면 DateTime이 필요합니다. Timespan이 아니고 – adam3039
Timespan이 필요합니다. 그 이유는 그 설정 값에서'datetime'을 생성했기 때문입니다 –