Код: Выделить всё
public Jwe generateAccessToken(AccessTokenDto dto) throws Exception {
return generateToken(
dto.getId().toString(),
Map.of(
"dto", dto,
"dtoClassName", dto.getClass().getName()
),
config.getAccessTokenExpiration()
);
}
private Jwe generateToken(String subject, Map claims, long expiration) throws Exception {
var claimSetBuilder = new JWTClaimsSet.Builder()
.subject(subject)
.issuer(config.getIssuer())
.issueTime(new Date())
.expirationTime(new Date(System.currentTimeMillis() + 1000 * expiration));
for (Map.Entry claimEntry : claims.entrySet()) {
if (claimEntry.getValue() instanceof String value) {
claimSetBuilder.claim(claimEntry.getKey(), value);
} else {
claimSetBuilder.claim(claimEntry.getKey(), serialise(claimEntry.getValue()));
}
}
return new Jwe(
claimSetBuilder.build(),
config.signingKey(),
config.encryptionKey()
);
}
private String serialise(Object dto) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(dto);
oos.close();
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
< /code>
, в то время как сам accessTokendto выглядит следующим образом: < /p>
@Data
public class AccessTokenDto implements Serializable {
@ValidUserId
private UUID id;
@ValidUserRole
private Role role;
}
< /code>
Когда я позже захочу получить от уже успешно проанализированного jwe, я использую эти три метода: < /p>
public T toDto() throws IOException {
Class type = (Class) getDtoClass();
Object deserializedDto = deserialize();
if (!type.isInstance(deserializedDto)) {
return null;
}
return type.cast(deserializedDto);
}
private Class getDtoClass() throws IOException {
String className = (String) claims.getClaim("dtoClassName");
Class type = null;
try {
type = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new IOException("When deserialzing Token - No Class with Name: " + className);
}
return type;
}
private Object deserialize() {
Object serializedDto = claims.getClaim("dto");
if (!(serializedDto instanceof String)) {
return null;
}
byte[] data = Base64.getDecoder().decode(serializedDto.toString());
try {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
Object obj = ois.readObject();
ois.close();
return obj;
} catch (Exception e) {
System.out.println("Error while deserializing token");
}
return null;
}
< /code>
Я знаю, что этот код работает, и я также знаю, что не должно быть проблемы, поскольку утверждение «dtoclassname» является правильно устанавливаемой при генерации токена. (До тех пор, пока я кодирую метод, чтобы сгенерировать токены правильно.) Но IntelliJ дает предупреждение о неконтролируемом актере, от которого я хотел бы избавиться.public T toDto() throws IOException {
Class type = (Class) getDtoClass();
Object deserializedDto = deserialize();
if (!type.isInstance(deserializedDto)) {
return null;
}
return type.cast(deserializedDto);
}
Я немного экспериментировал с опционами
Код: Выделить всё
public Optional toDto() {
Class targetType = getDtoClass();
Object deserializedDto = deserialize();
if (!targetType.isInstance(deserializedDto)) {
return Optional.empty();
}
return Optional.of(targetType.cast(deserializedDto));
}
Я где -то читал, что такой сценарий не может быть проверен, потому что это проблема с компиляцией, а не проблема времени выполнения, но я не уверен.
Подробнее здесь: https://stackoverflow.com/questions/797 ... -a-generic
Мобильная версия