Am trecut peste o problemă similară (clientul meu mi-a cerut să înregistrez ID-ul clientului) și am ajuns să caut o soluție. Privind codul sursă și modul în care este populat jurnalul de acces, vă pot spune că există un decalaj destul de mare între locul în care se formează jurnalul și locul în care se realizează munca.
Dacă aruncați o privire pe Keycloak, se bazează pe Wildfly, care folosește Undertow pentru a găzdui funcționalitatea serverului http. În timp ce intrarea în jurnalul de acces este emisă odată ce cererea a fost servită, există puține lacune și abstracții care complică lucrurile.
Din perspectiva software-ului, există handler undertow, apoi servlet, apoi servlet Restasy, apoi aplicație keycloak și resurse specifice. Când utilizați utilizatorul Keycloak sau consola de administrare, atunci în majoritatea locurilor este un client „subțire” care este redat de un browser web. Și acest browser numește rest resource.
Dacă doriți să obțineți destul de des informații legate de utilizator, acestea nu vor fi găsite în sesiune, deoarece cea mai mare parte a muncii efectuate de Kecloak este emiterea de token-uri în numele utilizatorilor. În mod formal, clientul care trimite cererea acționează în numele utilizatorului, ceea ce înseamnă că nu este o informație explicită disponibilă pentru fiecare solicitare primită. În plus, majoritatea resurselor de odihnă, prin definiție, sunt apatride, ceea ce înseamnă că funcționează cumva cu utilizatorul, dar nu populează prea mult sesiunea.
Doar o parte pentru care puteți conta pe accesul la informațiile utilizatorului este atunci când utilizatorul se conectează și face ceva în consola contului de utilizator. Pe lângă asta, ar putea fi o luptă pierdută, deoarece resursele keycloak care emit token-uri în majoritatea cazurilor se vor ocupa de sesiuni legate de client sau client.
La obiect - am ajuns la punctul în care am localizat locul care face analiza formatului jurnalului de acces. Se bazează pe Undertow ExchangeAtribute
idee care vă permite să vă aduceți propria macrocomandă pentru jurnal. Această macrocomandă poate fi utilizată fie pentru a traversa structurile de memorie în căutarea informațiilor necesare. Pentru mine a fost un client_id care făcea treaba. Pentru asta am ajuns la implementarea unui FormAttribute
. Încă trebuie să găsesc o modalitate de a-l conecta, dar din perspectiva testului unitar deja „a făcut clic”, vezi cât de de bază este codul:
pachetul org.code_house.wildfly.stuff.undertow.attributes;
// amintiți-vă să creați META-INF/services/io.undertow.attribute.ExchangeAttributeBuilder
// cu linia care conține numele clasei, de exemplu.
// org.code_house.wildfly.stuff.undertow.attributes.FormAttribute$Builder
/**
* Expuneți parametrii formularului în cadrul atributelor de schimb care pot fi autentificate în jurnalul de acces.
* Folosiți %{F,*} pentru a descărca toți parametrii sau %{F,client_id} pentru a reda selectat din câmp.
*
* @autor Åukasz Dywicki @ code-house.org
**/
clasa publică FormAttribute implementează ExchangeAttribute {
Private final String paramName;
public FormAttribute(String paramName) {
this.paramName = paramName;
}
@Trece peste
public String readAttribute(HttpServerExchange exchange) {
FormData formData = exchange.getAttachment(FormDataParser.FORM_DATA);
dacă ("*".equals(paramName)) {
returnează „” + formData;
}
return formData == null? "" : "" + formData.get(paramName);
}
@Trece peste
public void writeAttribute(HttpServerExchange exchange, String newValue) aruncă ReadOnlyAttributeException {
aruncă o nouă excepție ReadOnlyAttributeException ("Form", newValue);
}
Public static final class Builder implementează ExchangeAttributeBuilder {
@Trece peste
public String name() {
returnează „formular”;
}
@Trece peste
public ExchangeAttribute build (semnal String final) {
if (token.startsWith("%{F,") && token.endsWith("}")) {
final String paramName = token.substring(4, token.length() - 1);
returnează nou FormAttribute(paramName);
}
returnează nul;
}
@Trece peste
public int priority() {
returnează 0;
}
}
}
Punctul principal - prin utilizarea atributului de formular la valoarea de înregistrare introdusă în câmpul „nume utilizator” al formularului de conectare pentru a obține „cine”, atunci puteți combina acest lucru cu cookie-ul de sesiune care va fi reținut de browser. Prin fuziunea de bază a doi ași de mai sus puteți obține rezultatul necesar.
Folosind planul de mai sus, puteți implementa propriul lucru și puteți urmări jetoanele și alte lucruri care vă vor permite să vă construiți aplicația.
S-ar putea să actualizez răspunsul atunci când găsesc o logică adeziv pentru a injecta în mod corespunzător un atribut suplimentar în formatul de jurnal în undertow.
EDIT: Doar o modalitate pe care am găsit-o până acum de a injecta atribute suplimentare este prin a le copia în $JBOSS_HOME/modules/system/layers/base/org/wildfly/extension/undertow/main/
si actualizare module.xml
în acest director:
<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>