mirror of https://github.com/jwtk/jjwt.git
Merge pull request #172 from sainaen/numeric_claims_fix_typing
Implement type conversions of integral claim values
This commit is contained in:
commit
48dae365b1
|
@ -120,10 +120,25 @@ public class DefaultClaims extends JwtMap implements Claims {
|
||||||
value = getDate(claimName);
|
value = getDate(claimName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return castClaimValue(value, requiredType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T castClaimValue(Object value, Class<T> requiredType) {
|
||||||
if (requiredType == Date.class && value instanceof Long) {
|
if (requiredType == Date.class && value instanceof Long) {
|
||||||
value = new Date((Long)value);
|
value = new Date((Long)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value instanceof Integer) {
|
||||||
|
int intValue = (Integer) value;
|
||||||
|
if (requiredType == Long.class) {
|
||||||
|
value = (long) intValue;
|
||||||
|
} else if (requiredType == Short.class && Short.MIN_VALUE <= intValue && intValue <= Short.MAX_VALUE) {
|
||||||
|
value = (short) intValue;
|
||||||
|
} else if (requiredType == Byte.class && Byte.MIN_VALUE <= intValue && intValue <= Byte.MAX_VALUE) {
|
||||||
|
value = (byte) intValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!requiredType.isInstance(value)) {
|
if (!requiredType.isInstance(value)) {
|
||||||
throw new RequiredTypeException("Expected value to be of type: " + requiredType + ", but was " + value.getClass());
|
throw new RequiredTypeException("Expected value to be of type: " + requiredType + ", but was " + value.getClass());
|
||||||
}
|
}
|
||||||
|
|
|
@ -716,6 +716,37 @@ class JwtParserTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testParseClaimsJwsWithNumericTypes() {
|
||||||
|
byte[] key = randomKey()
|
||||||
|
|
||||||
|
def b = (byte) 42
|
||||||
|
def s = (short) 42
|
||||||
|
def i = 42
|
||||||
|
|
||||||
|
def smallLong = (long) 42
|
||||||
|
def bigLong = ((long) Integer.MAX_VALUE) + 42
|
||||||
|
|
||||||
|
String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key).
|
||||||
|
claim("byte", b).
|
||||||
|
claim("short", s).
|
||||||
|
claim("int", i).
|
||||||
|
claim("long_small", smallLong).
|
||||||
|
claim("long_big", bigLong).
|
||||||
|
compact()
|
||||||
|
|
||||||
|
Jwt<Header,Claims> jwt = Jwts.parser().setSigningKey(key).parseClaimsJws(compact)
|
||||||
|
|
||||||
|
Claims claims = jwt.getBody()
|
||||||
|
|
||||||
|
assertEquals(b, claims.get("byte", Byte.class))
|
||||||
|
assertEquals(s, claims.get("short", Short.class))
|
||||||
|
assertEquals(i, claims.get("int", Integer.class))
|
||||||
|
assertEquals(smallLong, claims.get("long_small", Long.class))
|
||||||
|
assertEquals(bigLong, claims.get("long_big", Long.class))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// parsePlaintextJws with signingKey resolver.
|
// parsePlaintextJws with signingKey resolver.
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
|
@ -52,11 +52,103 @@ class DefaultClaimsTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetClaimWithRequiredType_Success() {
|
void testGetClaimWithRequiredType_Integer_Success() {
|
||||||
claims.put("anInteger", new Integer(5))
|
def expected = new Integer(5)
|
||||||
|
claims.put("anInteger", expected)
|
||||||
Object result = claims.get("anInteger", Integer.class)
|
Object result = claims.get("anInteger", Integer.class)
|
||||||
|
assertEquals(expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
assertTrue(result instanceof Integer)
|
@Test
|
||||||
|
void testGetClaimWithRequiredType_Long_Success() {
|
||||||
|
def expected = new Long(123)
|
||||||
|
claims.put("aLong", expected)
|
||||||
|
Object result = claims.get("aLong", Long.class)
|
||||||
|
assertEquals(expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetClaimWithRequiredType_LongWithInteger_Success() {
|
||||||
|
// long value that fits inside an Integer
|
||||||
|
def expected = new Long(Integer.MAX_VALUE - 100)
|
||||||
|
// deserialized as an Integer from JSON
|
||||||
|
// (type information is not available during parsing)
|
||||||
|
claims.put("smallLong", expected.intValue())
|
||||||
|
// should still be available as Long
|
||||||
|
Object result = claims.get("smallLong", Long.class)
|
||||||
|
assertEquals(expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetClaimWithRequiredType_ShortWithInteger_Success() {
|
||||||
|
def expected = new Short((short) 42)
|
||||||
|
claims.put("short", expected.intValue())
|
||||||
|
Object result = claims.get("short", Short.class)
|
||||||
|
assertEquals(expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetClaimWithRequiredType_ShortWithBigInteger_Exception() {
|
||||||
|
claims.put("tooBigForShort", ((int) Short.MAX_VALUE) + 42)
|
||||||
|
try {
|
||||||
|
claims.get("tooBigForShort", Short.class)
|
||||||
|
fail("getClaim() shouldn't silently lose precision.")
|
||||||
|
} catch (RequiredTypeException e) {
|
||||||
|
assertEquals(
|
||||||
|
e.getMessage(),
|
||||||
|
"Expected value to be of type: class java.lang.Short, but was class java.lang.Integer"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetClaimWithRequiredType_ShortWithSmallInteger_Exception() {
|
||||||
|
claims.put("tooSmallForShort", ((int) Short.MIN_VALUE) - 42)
|
||||||
|
try {
|
||||||
|
claims.get("tooSmallForShort", Short.class)
|
||||||
|
fail("getClaim() shouldn't silently lose precision.")
|
||||||
|
} catch (RequiredTypeException e) {
|
||||||
|
assertEquals(
|
||||||
|
e.getMessage(),
|
||||||
|
"Expected value to be of type: class java.lang.Short, but was class java.lang.Integer"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetClaimWithRequiredType_ByteWithInteger_Success() {
|
||||||
|
def expected = new Byte((byte) 42)
|
||||||
|
claims.put("byte", expected.intValue())
|
||||||
|
Object result = claims.get("byte", Byte.class)
|
||||||
|
assertEquals(expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetClaimWithRequiredType_ByteWithBigInteger_Exception() {
|
||||||
|
claims.put("tooBigForByte", ((int) Byte.MAX_VALUE) + 42)
|
||||||
|
try {
|
||||||
|
claims.get("tooBigForByte", Byte.class)
|
||||||
|
fail("getClaim() shouldn't silently lose precision.")
|
||||||
|
} catch (RequiredTypeException e) {
|
||||||
|
assertEquals(
|
||||||
|
e.getMessage(),
|
||||||
|
"Expected value to be of type: class java.lang.Byte, but was class java.lang.Integer"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetClaimWithRequiredType_ByteWithSmallInteger_Exception() {
|
||||||
|
claims.put("tooSmallForByte", ((int) Byte.MIN_VALUE) - 42)
|
||||||
|
try {
|
||||||
|
claims.get("tooSmallForByte", Byte.class)
|
||||||
|
fail("getClaim() shouldn't silently lose precision.")
|
||||||
|
} catch (RequiredTypeException e) {
|
||||||
|
assertEquals(
|
||||||
|
e.getMessage(),
|
||||||
|
"Expected value to be of type: class java.lang.Byte, but was class java.lang.Integer"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue