Регистрация имени пользователя в журнале доступа KeyCloak
В KeyCLoak 15.0 (то есть WildFly 23.0) я пытаюсь настроить журнал доступа, чтобы он также включал имя пользователя (или любой идентификатор пользователя), когда пользователь входит в систему.keycloak/standalone/configuration/standalone.xml
, я настроилXML:/server/profile/subsystem[@xmlns="urn:jboss:domain:undertow:12.0"]/server/host/access-log/@pattern
pattern="%h %l %u %t "%r" %s/%S %b %T %I "%{i,User-Agent}""
Журнал правильно печатается в файле, который я настроил. Однако значение или всегда пусто (т.е.-
).
Единственный способ зарегистрировать какой-либо идентификатор пользователя, который я нашел, - это записать значение файла cookie сеанса с помощью%{c,KEYCLOAK_SESSION}
(это содержитrealm/user-ID/secret
). Что не очень хорошая идея делать в производстве.
Есть идеи, как записать имя пользователя или идентификатор пользователя в журнал доступа?
Это ошибка KeyCLoak, которая%u
или%{REMOTE_USER}
пуст, даже если в KeyCloak есть активный сеанс пользователя? Или можно ли в KeyCLoak настроить, какое значение атрибута пользователя входит вREMOTE_USER
?
Альтернативно, как поместить идентификатор пользователя в какой-либо заголовок, чтобы использовать одно из следующих действий?
-
%{i,xxx}
для входящих заголовков -
%{o,xxx}
для заголовков исходящих ответов -
%{c,xxx}
для определенного файла cookie -
%{r,xxx}
где xxx — атрибут в ServletRequest -
%{s,xxx}
где xxx — атрибут в HttpSession
Среди прочего я попробовал эти. Ни один из них не был заселен.
%{s,user}
%{s,userId}
%{s,client_id}
%{s,USER_ID}
%{s,USER}
%{s,org.keycloak.adapters.spi.KeycloakAccount}
%{s,KeycloakAccount}
%{s,org.keycloak.adapters.tomcat.CatalinaSessionTokenStore.SerializableKeycloakAccount}
%{s,SerializableKeycloakAccount}
%{s,org.keycloak.adapters.saml.SamlSession}
%{s,SamlSession}
%{s,org.keycloak.adapters.undertow.KeycloakUndertowAccount}
%{s,KeycloakUndertowAccount}
%{s,org.keycloak.KeycloakSecurityContext}
%{s,KeycloakSecurityContext}
%{s,io.undertow.servlet.util.SavedRequest}
%{s,SavedRequest}
%{r,tokenInfo}
%{r,KeycloakSecurityContext}
%{r,ElytronHttpFacade}
%{r,AdapterDeploymentContext}
%{r,TOKEN_STORE_NOTE}
1 ответ
Я столкнулся с аналогичной проблемой (мой клиент попросил меня записать идентификатор клиента) и в итоге начал искать решение. Глядя на исходный код и на то, как заполняется журнал доступа, я могу сказать вам, что существует довольно большой разрыв между тем, где формируется журнал, и тем, где выполняется фактическая работа.
Если вы посмотрите на Keycloak, он основан на Wildfly, который использует Undertow для размещения функций http-сервера. Хотя запись в журнале доступа создается после того, как запрос был обслужен, существует несколько пробелов и абстракций, которые усложняют ситуацию.
С точки зрения программного обеспечения есть обработчик подвода, затем сервлет, затем сервлет resteasy, затем приложение keycloak и определенные ресурсы. Когда вы используете консоль пользователя или администратора Keycloak, то в большинстве случаев это «тонкий» клиент, который отображается в веб-браузере. И этот браузер называет ресурс отдыха.
Если вы хотите получать информацию, связанную с пользователем, довольно часто, ее нельзя будет найти в сеансе, поскольку большая часть работы, выполняемой Kecloak, заключается в выпуске токенов от имени пользователей. Формально клиент, отправляющий запрос, действует от имени пользователя, а это означает, что для каждого входящего запроса не существует явной информации. Кроме того, большинство остальных ресурсов по определению не имеют состояния, что означает, что они каким-то образом работают с пользователем, но не сильно заполняют сеанс. Только одна часть, в отношении которой вы можете рассчитывать на доступ к информации пользователя, — это когда пользователь действительно входит в систему и делает что-то в консоли учетной записи пользователя. Кроме того, это может быть проиграно, поскольку ресурсы keycloak, выдающие токены, в большинстве случаев будут обрабатывать клиентские или связанные с клиентом сеансы.
К делу - я подхожу к месту, где находится место, которое выполняет синтаксический анализ формата журнала доступа. Он основан на Undertow
package org.code_house.wildfly.stuff.undertow.attributes;
// remember to create META-INF/services/io.undertow.attribute.ExchangeAttributeBuilder
// with line containing class name, ie.
// org.code_house.wildfly.stuff.undertow.attributes.FormAttribute$Builder
/**
* Expose form parameters within exchange attributes which can be logged in access log.
* Use %{F,*} to dump all params or %{F,client_id} to render selected from field.
*
* @author Łukasz Dywicki @ code-house.org
**/
public class FormAttribute implements ExchangeAttribute {
private final String paramName;
public FormAttribute(String paramName) {
this.paramName = paramName;
}
@Override
public String readAttribute(HttpServerExchange exchange) {
FormData formData = exchange.getAttachment(FormDataParser.FORM_DATA);
if ("*".equals(paramName)) {
return "" + formData;
}
return formData == null ? "" : "" + formData.get(paramName);
}
@Override
public void writeAttribute(HttpServerExchange exchange, String newValue) throws ReadOnlyAttributeException {
throw new ReadOnlyAttributeException("Form", newValue);
}
public static final class Builder implements ExchangeAttributeBuilder {
@Override
public String name() {
return "form";
}
@Override
public ExchangeAttribute build(final String token) {
if (token.startsWith("%{F,") && token.endsWith("}")) {
final String paramName = token.substring(4, token.length() - 1);
return new FormAttribute(paramName);
}
return null;
}
@Override
public int priority() {
return 0;
}
}
}
Основной момент - используя атрибут формы для регистрации значения, введенного в поле «имя пользователя» формы входа в систему, чтобы получить «кто», вы можете объединить это с файлом cookie сеанса, который будет сохранен браузером. Путем базового слияния двух вышеперечисленных тузов вы сможете добиться необходимого результата. Используя приведенный выше план, вы можете реализовать свою собственную вещь и отслеживать токены и другие вещи, которые позволят вам создать свое приложение.
Я могу обновить ответ, когда найду связующую логику для правильного внедрения дополнительных атрибутов в формат журнала в Undertow. РЕДАКТИРОВАТЬ: Единственный способ, который я нашел до сих пор, — это добавить дополнительные атрибуты, скопировав их в
<module name="org.wildfly.extension.undertow" xmlns="urn:jboss:module:1.5">
...
<resources>
<resource-root path="wildfly-undertow-20.0.1.Final.jar"/>
<!-- put here name of jar you made -->
<resource-root path="undertow-client-request-filter-1.0.0-SNAPSHOT.jar"/>
</resources>
...
</module>