두리공장
[keycloak] User Storage SPI 사용시 Create at 필드 동기화 본문
지난번에 singular-keycloak-database-federation 를 사용하여 keycloak 에서 external Database 를 연결하는 것을 시도해 보았다.
동기화는 잘 되었는데 user 에 보면 create at 부분이 "invalid Date" 라고 뜨는 문제가 있다.
여기에 날짜를 정상적으로 보여주기로 했다.
UserAdapter 는 AbstractUserAdapterFederatedStorage 를 상속하여 사용하는데,
이걸 열어보면,
public static String FIRST_NAME_ATTRIBUTE = "FIRST_NAME";
public static String LAST_NAME_ATTRIBUTE = "LAST_NAME";
public static String EMAIL_ATTRIBUTE = "EMAIL";
public static String EMAIL_VERIFIED_ATTRIBUTE = "EMAIL_VERIFIED";
public static String CREATED_TIMESTAMP_ATTRIBUTE = "CREATED_TIMESTAMP";
public static String ENABLED_ATTRIBUTE = "ENABLED";
이렇게 되어 있다. 속성값으로 createdTimestamp 를 사용하는 것이다. get / set 메서드가 지원되기에 이걸 사용하면 외부DB에 있는 값은 바인딩할 수 있겠다.
먼저 UserAdapter 에 createTime 을 셋팅하도록 코드를 수정했다.
public UserAdapter(KeycloakSession session, RealmModel realm, ComponentModel model, Map<String, String> data, boolean allowDatabaseToOverwriteKeycloak, List<Map<String, String>> userRoles) {
super(session, realm, model);
this.keycloakId = StorageId.keycloakId(model, data.get("id"));
this.username = data.get("username");
this.userRoles = userRoles;
try {
Map<String, List<String>> attributes = this.getAttributes();
for (Entry<String, String> e : data.entrySet()) {
Set<String> newValues = new HashSet<>();
if (!allowDatabaseToOverwriteKeycloak) {
List<String> attribute = attributes.get(e.getKey());
if (attribute != null) {
newValues.addAll(attribute);
}
}
newValues.add(StringUtils.trimToNull(e.getValue()));
this.setAttribute(e.getKey(), newValues.stream().filter(Objects::nonNull).collect(Collectors.toList()));
}
// create Time 을 가져온다.
log.info("createdTimestamp:" + data.get("createdTimestamp"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
if(!data.get("createdTimestamp").isEmpty() || data.get("createdTimestamp") != null) {
Date dt = sdf.parse(data.get("createdTimestamp"));
this.setCreatedTimestamp(dt.getTime());
}
} catch(Exception e) {
log.errorv(e, "UserAdapter constructor, username={0}", this.username);
}
}
이렇게 하면, Map<String, String> data 로 받는 값에서 createdTimestamp 값을 꺼내어 this.setCreatedTimestamp(dt.getTime()); 으로 값을 넣을 수 있다.
DB 에 cratedTimestamp 필드를 추가하고 timestamp 형식으로 값을 추가하자
alter table users add column
"createdTimestamp" timestamp;
update users set
"createdTimestamp" = now()
where id='durifac';
그리고 SPI 의 쿼리문에도 createdTimestamp 필드를 추가해준다. (참고로 postgresql 은 대소문자를 구분하므로, 필드명은 쌍따옴표로 묶어준다.
select id, "createdTimestamp", username, email, firstName, lastName, cpf, fullName from public.users
도커를 재기동하자(restart)
이제 정상적으로 표시된다.
끝
'cloud' 카테고리의 다른 글
스프링부트에서 keycloak admin restAPI를 사용하려면,,, (0) | 2023.10.29 |
---|---|
[ELK] 엘라스틱서치에서 logstash 로 RDBMS 데이터 pipeline으로 연결하기 (0) | 2023.06.17 |
[keycloak] SPI 에서 custom role 연동하기 (0) | 2023.06.07 |
[keycloak] SPI (service provider interface) 를 이용하여 사용자DB를 연결하기 (version 20.0.5) (0) | 2023.05.22 |