Skip to content

Commit

Permalink
* [GovWayCore]
Browse files Browse the repository at this point in the history
Risolta anomalia che si verificava in alcuni casi limite durante il tracciamento delle fruizioni di API con negoziazione token.
L'errore segnalato nei log era:
     "PostOutResponseHandler [transazioni]Errore durante la scrittura della transazione sul database (Lettura dati Transazione): Caused by: java.util.ConcurrentModificationException
                   at java.util.HashMap$HashIterator.nextNode(HashMap.java)
                   ...
                   at org.openspcoop2.pdd.core.token.TokenUtilities.replaceTokenInMap(TokenUtilities.java)
  • Loading branch information
andreapoli committed Feb 2, 2024
1 parent 9401cc0 commit 512a21f
Show file tree
Hide file tree
Showing 42 changed files with 1,268 additions and 509 deletions.
11 changes: 11 additions & 0 deletions ChangeLog
@@ -1,3 +1,14 @@
2024-02-02 Andrea Poli <apoli@link.it>

* [GovWayCore]
Risolto Bug OP-1706
Risolta anomalia che si verificava in alcuni casi limite durante il tracciamento delle fruizioni di API con negoziazione token.
L'errore segnalato nei log era:
"PostOutResponseHandler [transazioni]Errore durante la scrittura della transazione sul database (Lettura dati Transazione): Caused by: java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java)
...
at org.openspcoop2.pdd.core.token.TokenUtilities.replaceTokenInMap(TokenUtilities.java)

2024-02-01 Giuliano Pintori <pintori@link.it>

* [GovWayMonitor, ApiRsMonitoraggio]
Expand Down
Expand Up @@ -223,7 +223,7 @@ public Map<String, String> getTokenClaims() {
return this.tokenClaims;
}

public void setTokenClaims(Map<String, Object> tokenClaims) {
public void setTokenClaims(Map<String, Serializable> tokenClaims) {
this.tokenClaims = new HashMap<>();
if(tokenClaims!=null && !tokenClaims.isEmpty()) {
for (String key : tokenClaims.keySet()) {
Expand Down
11 changes: 6 additions & 5 deletions core/src/org/openspcoop2/pdd/config/PDNDResolver.java
Expand Up @@ -32,6 +32,7 @@
import org.openspcoop2.pdd.core.keystore.KeystoreException;
import org.openspcoop2.pdd.core.keystore.RemoteStoreProvider;
import org.openspcoop2.pdd.core.token.InformazioniToken;
import org.openspcoop2.pdd.core.token.TokenUtilities;
import org.openspcoop2.pdd.core.transazioni.Transaction;
import org.openspcoop2.pdd.core.transazioni.TransactionContext;
import org.openspcoop2.pdd.core.transazioni.TransactionDeletedException;
Expand Down Expand Up @@ -318,7 +319,7 @@ private void enrichTokenInfo(SecurityToken securityTokenForContext, Informazioni
}
private void enrichTokenInfoAddInClaims(JSONUtils jsonUtils, SecurityToken securityTokenForContext, InformazioniToken informazioniTokenNormalizzate, JsonNode root, String type,
PDNDTokenInfoDetails info) {
Map<String, Object> readClaims = jsonUtils.convertToSimpleMap(root);
Map<String, Serializable> readClaims = jsonUtils.convertToSimpleMap(root);
if(!readClaims.isEmpty()) {
enrichTokenInfoAddInClaims(securityTokenForContext, informazioniTokenNormalizzate,
type, info,
Expand All @@ -328,18 +329,18 @@ private void enrichTokenInfoAddInClaims(JSONUtils jsonUtils, SecurityToken secur

private void enrichTokenInfoAddInClaims(SecurityToken securityTokenForContext, InformazioniToken informazioniTokenNormalizzate,
String type, PDNDTokenInfoDetails info,
Map<String, Object> readClaims) {
informazioniTokenNormalizzate.getPdnd().put(type,readClaims);
Map<String, Serializable> readClaims) {
informazioniTokenNormalizzate.getPdnd().put(type,TokenUtilities.toHashMapSerializable(readClaims));
String prefix = PDNDTokenInfo.TOKEN_INFO_PREFIX_PDND+type+".";
Map<String, Serializable> readClaimsSerializable = new HashMap<>();
if(informazioniTokenNormalizzate.getClaims()!=null) {
for (Map.Entry<String,Object> entry : readClaims.entrySet()) {
for (Map.Entry<String,Serializable> entry : readClaims.entrySet()) {
String key = prefix+entry.getKey();
if(!informazioniTokenNormalizzate.getClaims().containsKey(key)) {
informazioniTokenNormalizzate.getClaims().put(key, entry.getValue());
}
if(entry.getValue() instanceof Serializable) {
readClaimsSerializable.put(entry.getKey(), (Serializable) entry.getValue());
readClaimsSerializable.put(entry.getKey(), entry.getValue());
}
}
}
Expand Down
Expand Up @@ -23,6 +23,7 @@
package org.openspcoop2.pdd.core.autorizzazione;

import java.io.File;
import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -200,9 +201,9 @@ public static XacmlRequest newXacmlRequest(IProtocolFactory<?> protocolFactory,

InformazioniToken informazioniTokenNormalizzate = null;
InformazioniTokenUserInfo informazioniTokenUserInfoNormalizzate = null;
Map<String, Object> jwtClaims = null;
Map<String, Object> introspectionClaims = null;
Map<String, Object> userInfoClaims = null;
Map<String, Serializable> jwtClaims = null;
Map<String, Serializable> introspectionClaims = null;
Map<String, Serializable> userInfoClaims = null;
Object oInformazioniTokenNormalizzate = pddContext.getObject(org.openspcoop2.pdd.core.token.Costanti.PDD_CONTEXT_TOKEN_INFORMAZIONI_NORMALIZZATE);
if(oInformazioniTokenNormalizzate!=null) {
informazioniTokenNormalizzate = (InformazioniToken) oInformazioniTokenNormalizzate;
Expand Down Expand Up @@ -241,7 +242,7 @@ public static XacmlRequest newXacmlRequest(IProtocolFactory<?> protocolFactory,
}

List<String> attributeNames = null;
Map<String, Object> attributes = null;
Map<String, Serializable> attributes = null;
boolean multipleAA = false;
InformazioniAttributi informazioniAttributiNormalizzati = null;
Object oInformazioniAttributiNormalizzati = pddContext.getObject(org.openspcoop2.pdd.core.token.Costanti.PDD_CONTEXT_ATTRIBUTI_INFORMAZIONI_NORMALIZZATE);
Expand Down Expand Up @@ -766,7 +767,7 @@ private static Map<String,String> readConfig(PdDContext pddContext, MapKey<Strin
return null;
}

private static void addAttributes(XacmlRequest xacmlRequest, Map<String, Object> attributesParam, boolean multipleAA) {
private static void addAttributes(XacmlRequest xacmlRequest, Map<String, Serializable> attributesParam, boolean multipleAA) {
if(attributesParam!=null && !attributesParam.isEmpty()) {
String logAA = "";
if(multipleAA) {
Expand All @@ -777,7 +778,7 @@ private static void addAttributes(XacmlRequest xacmlRequest, Map<String, Object>
try {
List<String> attributesNames = new ArrayList<>();
@SuppressWarnings("unchecked")
Map<String, Object> attributes = (Map<String, Object>) o;
Map<String, Serializable> attributes = (Map<String, Serializable>) o;
if(attributes!=null && !attributes.isEmpty()) {
for (String attrName : attributes.keySet()) {
if(!attributesNames.contains(attrName)) {
Expand Down Expand Up @@ -817,7 +818,7 @@ private static void addAttributes(XacmlRequest xacmlRequest, Map<String, Object>
}
}
}
private static void addAttribute(XacmlRequest xacmlRequest, String xacmlIdPrefix, Map<String, Object> attributes, String attributeName,
private static void addAttribute(XacmlRequest xacmlRequest, String xacmlIdPrefix, Map<String, Serializable> attributes, String attributeName,
JSONUtils jsonUtils, String logAA) {
Object oValue = attributes.get(attributeName);
if(oValue!=null) {
Expand Down
Expand Up @@ -192,7 +192,7 @@ else if(transportResponseContext!=null) {
}

if(root!=null) {
Map<String, Object> readClaims = jsonUtils.convertToSimpleMap(root);
Map<String, Serializable> readClaims = jsonUtils.convertToSimpleMap(root);
if(readClaims!=null && readClaims.size()>0) {
this.claims.putAll(readClaims);
}
Expand All @@ -208,7 +208,7 @@ else if(transportResponseContext!=null) {
private transient Logger log;

// Informazioni
private Map<String, Object> integrationInfo;
private Map<String, Serializable> integrationInfo;

// Claims
private Map<String,Object> claims = new HashMap<>();
Expand All @@ -226,13 +226,13 @@ else if(transportResponseContext!=null) {
private boolean sourceRequired;


public Map<String, Object> getIntegrationInfo() {
public Map<String, Serializable> getIntegrationInfo() {
return this.integrationInfo;
}
public Map<String, Object> getInfo() {
public Map<String, Serializable> getInfo() {
return this.integrationInfo;
}
public void setIntegrationInfo(Map<String, Object> integrationInfo) {
public void setIntegrationInfo(Map<String, Serializable> integrationInfo) {
this.integrationInfo = integrationInfo;
}
public List<String> getInfoNames(){
Expand Down
Expand Up @@ -1264,63 +1264,83 @@ else if(transaction.getServiziApplicativiErogatore()!=null && transaction.getSer
// token negoziazione
InformazioniNegoziazioneToken informazioniNegoziazioneToken = null;
if(this.transazioniRegistrazioneRetrieveToken_saveAsTokenInfo) {
informazioniNegoziazioneToken = transaction.getInformazioniNegoziazioneToken();
if(transaction.getInformazioniNegoziazioneToken()!=null) {
informazioniNegoziazioneToken = transaction.getInformazioniNegoziazioneToken();
if(
(
op2Properties.isGestioneRetrieveToken_saveAsTokenInfo_excludeJwtSignature() &&
(informazioniNegoziazioneToken.getAccessToken()!=null || informazioniNegoziazioneToken.getRefreshToken()!=null)
)
||
(
op2Properties.isGestioneRetrieveToken_grantType_rfc7523_saveClientAssertionJWTInfo_excludeJwtSignature() &&
informazioniNegoziazioneToken.getRequest()!=null
)
) {
// clone for fix 'Caused by: java.util.ConcurrentModificationException' e non modificare informazione in cache dovuto alla deleteSignature e alla sostituzione del token
informazioniNegoziazioneToken = (InformazioniNegoziazioneToken) informazioniNegoziazioneToken.clone();
}
}

if(informazioniNegoziazioneToken!=null) {
if(op2Properties.isGestioneRetrieveToken_saveAsTokenInfo_excludeJwtSignature()) {
if(informazioniNegoziazioneToken.getAccessToken()!=null) {
String originale = informazioniNegoziazioneToken.getAccessToken();
String senzaSignature = TokenUtilities.deleteSignature(informazioniNegoziazioneToken.getAccessToken());
informazioniNegoziazioneToken.setAccessToken(senzaSignature);
TokenUtilities.replaceTokenInMap(informazioniNegoziazioneToken.getClaims(), originale, senzaSignature);
informazioniNegoziazioneToken.setClaims(TokenUtilities.replaceTokenInMapByValue(informazioniNegoziazioneToken.getClaims(), originale, senzaSignature));
informazioniNegoziazioneToken.replaceInRawResponse(originale, senzaSignature);
}
if(informazioniNegoziazioneToken.getRefreshToken()!=null) {
String originale = informazioniNegoziazioneToken.getRefreshToken();
String senzaSignature = TokenUtilities.deleteSignature(informazioniNegoziazioneToken.getRefreshToken());
informazioniNegoziazioneToken.setRefreshToken(senzaSignature);
TokenUtilities.replaceTokenInMap(informazioniNegoziazioneToken.getClaims(), originale, senzaSignature);
informazioniNegoziazioneToken.setClaims(TokenUtilities.replaceTokenInMapByValue(informazioniNegoziazioneToken.getClaims(), originale, senzaSignature));
informazioniNegoziazioneToken.replaceInRawResponse(originale, senzaSignature);
}
}

if(informazioniNegoziazioneToken.getRequest()!=null) {
if(informazioniNegoziazioneToken.getRequest().getJwtClientAssertion()!=null &&
informazioniNegoziazioneToken.getRequest().getJwtClientAssertion().getToken()!=null) {
if(op2Properties.isGestioneRetrieveToken_grantType_rfc7523_saveClientAssertionJWTInfo_excludeJwtSignature()) {
informazioniNegoziazioneToken.getRequest().getJwtClientAssertion().setToken(TokenUtilities.deleteSignature(informazioniNegoziazioneToken.getRequest().getJwtClientAssertion().getToken()));
}
}
if(informazioniNegoziazioneToken.getRequest()!=null &&
informazioniNegoziazioneToken.getRequest().getJwtClientAssertion()!=null &&
informazioniNegoziazioneToken.getRequest().getJwtClientAssertion().getToken()!=null &&
op2Properties.isGestioneRetrieveToken_grantType_rfc7523_saveClientAssertionJWTInfo_excludeJwtSignature()) {
informazioniNegoziazioneToken.getRequest().getJwtClientAssertion().setToken(TokenUtilities.deleteSignature(informazioniNegoziazioneToken.getRequest().getJwtClientAssertion().getToken()));
}
}
}

// token info
if(this.transazioniRegistrazioneTokenInformazioniNormalizzate && transaction.getInformazioniToken()!=null) {

InformazioniToken informazioniToken = transaction.getInformazioniToken();
if(informazioniToken.getToken()!=null && op2Properties.isGestioneTokenSaveTokenInfoValidationFailedExcludeJwtSignature()) {
// clone for fix 'Caused by: java.util.ConcurrentModificationException' e non modificare informazione in cache dovuto alla deleteSignature e alla sostituzione del token
informazioniToken = (InformazioniToken) informazioniToken.clone();
}

// token validazione
if(transaction.getInformazioniToken().getToken()!=null && op2Properties.isGestioneTokenSaveTokenInfoValidationFailedExcludeJwtSignature()) {
transaction.getInformazioniToken().setToken(TokenUtilities.deleteSignature(transaction.getInformazioniToken().getToken()));
if(informazioniToken.getToken()!=null && op2Properties.isGestioneTokenSaveTokenInfoValidationFailedExcludeJwtSignature()) {
informazioniToken.setToken(TokenUtilities.deleteSignature(informazioniToken.getToken()));
}

// token negoziazione
if(informazioniNegoziazioneToken!=null) {
transaction.getInformazioniToken().setRetrievedToken(informazioniNegoziazioneToken);
informazioniToken.setRetrievedToken(informazioniNegoziazioneToken);
}

// attributi
InformazioniAttributi informazioniAttributi = null;
if(!this.transazioniRegistrazioneAttributiInformazioniNormalizzate) {
informazioniAttributi = transaction.getInformazioniToken().getAa();
transaction.getInformazioniToken().setAa(null);
informazioniAttributi = informazioniToken.getAa();
informazioniToken.setAa(null);
}
try {
transactionDTO.setTokenInfo(transaction.getInformazioniToken().toJson());
}catch(Throwable t) {
transactionDTO.setTokenInfo(informazioniToken.toJson());
}catch(Exception t) {
this.logger.error("Serializzazione informazioni token non riuscita: "+t.getMessage(),t);
}
if(informazioniAttributi!=null) {
transaction.getInformazioniToken().setAa(informazioniAttributi);
informazioniToken.setAa(informazioniAttributi);
}

}
Expand Down
Expand Up @@ -20,6 +20,7 @@
package org.openspcoop2.pdd.core.token;

import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
Expand Down Expand Up @@ -1385,7 +1386,7 @@ static void validazioneInformazioniTokenHeader(String jsonHeader, PolicyGestione
JSONUtils jsonUtils = JSONUtils.getInstance();
if(jsonUtils.isJson(jsonHeader)) {
JsonNode root = jsonUtils.getAsNode(jsonHeader);
Map<String, Object> readClaims = jsonUtils.convertToSimpleMap(root);
Map<String, Serializable> readClaims = jsonUtils.convertToSimpleMap(root);

validazioneInformazioniTokenHeader(readClaims, policyGestioneToken.getValidazioneJWTHeaderTyp(), Claims.JSON_WEB_TOKEN_RFC_7515_TYPE);

Expand All @@ -1402,7 +1403,7 @@ static void validazioneInformazioniTokenHeader(String jsonHeader, PolicyGestione

}

private static void validazioneInformazioniTokenHeader(Map<String, Object> readClaims, List<String> expectedValues, String claim) throws TokenException {
private static void validazioneInformazioniTokenHeader(Map<String, Serializable> readClaims, List<String> expectedValues, String claim) throws TokenException {
if(expectedValues!=null && !expectedValues.isEmpty()) {
String v = null;
if(readClaims!=null && !readClaims.isEmpty()) {
Expand Down
Expand Up @@ -37,7 +37,7 @@
* @author $Author$
* @version $Rev$, $Date$
*/
public class InformazioniJWTClientAssertion extends org.openspcoop2.utils.beans.BaseBean implements Serializable {
public class InformazioniJWTClientAssertion extends org.openspcoop2.utils.beans.BaseBean implements Serializable, Cloneable {

/**
*
Expand All @@ -55,21 +55,21 @@ public InformazioniJWTClientAssertion(Logger log, String base64, boolean infoNor
String hdrBase64 = split[0];
try {
this.jsonHeader = new String(Base64Utilities.decode(hdrBase64));
}catch(Throwable t) {
}catch(Exception t) {
log.error("Decode header failed (hdr: "+hdrBase64+" assertion:"+base64+"): "+t.getMessage(),t);
}
if(this.jsonHeader!=null) {
try {
JSONUtils jsonUtils = JSONUtils.getInstance();
if(jsonUtils.isJson(this.jsonHeader)) {
JsonNode root = jsonUtils.getAsNode(this.jsonHeader);
Map<String, Object> readClaims = jsonUtils.convertToSimpleMap(root);
Map<String, Serializable> readClaims = jsonUtils.convertToSimpleMap(root);
if(readClaims!=null && readClaims.size()>0) {
this.header = new HashMap<>();
this.header.putAll(readClaims);
}
}
}catch(Throwable t) {
}catch(Exception t) {
log.error("Decode header failed (json: "+this.jsonHeader+"): "+t.getMessage(),t);
}
}
Expand All @@ -78,21 +78,21 @@ public InformazioniJWTClientAssertion(Logger log, String base64, boolean infoNor
String payloadBase64 = split[1];
try {
this.jsonPayload = new String(Base64Utilities.decode(payloadBase64));
}catch(Throwable t) {
}catch(Exception t) {
log.error("Decode payload failed (payload: "+payloadBase64+" assertion:"+base64+"): "+t.getMessage(),t);
}
if(this.jsonPayload!=null) {
try {
JSONUtils jsonUtils = JSONUtils.getInstance();
if(jsonUtils.isJson(this.jsonPayload)) {
JsonNode root = jsonUtils.getAsNode(this.jsonPayload);
Map<String, Object> readClaims = jsonUtils.convertToSimpleMap(root);
Map<String, Serializable> readClaims = jsonUtils.convertToSimpleMap(root);
if(readClaims!=null && readClaims.size()>0) {
this.payload = new HashMap<>();
this.payload.putAll(readClaims);
}
}
}catch(Throwable t) {
}catch(Exception t) {
log.error("Decode payload failed (json: "+this.jsonPayload+"): "+t.getMessage(),t);
}
}
Expand All @@ -106,21 +106,21 @@ public InformazioniJWTClientAssertion(Logger log, String base64, boolean infoNor
// RawResponse
private String token;
// Claims
private Map<String,Object> header = null;
private Map<String,Object> payload = null;
private Map<String,Serializable> header = null;
private Map<String,Serializable> payload = null;
private String jsonHeader;
private String jsonPayload;

public Map<String, Object> getHeader() {
public Map<String, Serializable> getHeader() {
return this.header;
}
public void setHeader(Map<String, Object> header) {
public void setHeader(Map<String, Serializable> header) {
this.header = header;
}
public Map<String, Object> getPayload() {
public Map<String, Serializable> getPayload() {
return this.payload;
}
public void setPayload(Map<String, Object> payload) {
public void setPayload(Map<String, Serializable> payload) {
this.payload = payload;
}

Expand Down

0 comments on commit 512a21f

Please sign in to comment.