1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.portal.service.security.impl;
35
36 import java.nio.charset.Charset;
37 import java.nio.charset.StandardCharsets;
38 import java.security.MessageDigest;
39 import java.security.NoSuchAlgorithmException;
40
41 import com.fasterxml.jackson.core.JsonProcessingException;
42 import com.fasterxml.jackson.databind.ObjectMapper;
43 import fr.paris.lutece.api.user.User;
44 import fr.paris.lutece.portal.service.security.AccessLoggerConstants;
45 import fr.paris.lutece.portal.service.util.AppPropertiesService;
46 import fr.paris.lutece.portal.service.security.IAccessLogger;
47
48 import java.text.MessageFormat;
49 import org.apache.logging.log4j.Level;
50 import org.apache.logging.log4j.LogManager;
51 import org.apache.logging.log4j.Logger;
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public final class DefaultAccessLogger implements IAccessLogger
66 {
67
68 private static final Charset CONSTANT_HASH_ENCODING = StandardCharsets.UTF_8;
69 private static final String CONSTANT_HASH_DIGEST = "SHA-256";
70
71 private static final int CONSTANT_HASH_CHARACTERS_COUNT = 64;
72
73 private static final String PROPERTY_ADD_HASH_TO_LOGS = "accessLogger.defaultAccessLogger.addHashToLogs";
74 private static final String PROPERTY_ACCESSLOG_MESSAGE_FORMAT = "accessLogger.defaultAccessLogger.messageFormat";
75 private static final String PROPERTY_ACCESSLOG_MESSAGE_FORMAT_SEPARATOR = "accessLogger.defaultAccessLogger.messageFormatSeparator";
76
77 private static final String DEFAULT_ACCESSLOG_MESSAGE_FORMAT = "|{0}|{1}|{2}|{3}|{4}|{5}|";
78 private static final String DEFAULT_ACCESSLOG_MESSAGE_FORMAT_SEPARATOR = "|";
79
80 private static final String ERROR_MSG = "ERROR : unable to create json from data";
81
82 private final boolean _bAddHashToLogs = AppPropertiesService.getPropertyBoolean( PROPERTY_ADD_HASH_TO_LOGS, false );
83 private final String _messageFormat = AppPropertiesService.getProperty( PROPERTY_ACCESSLOG_MESSAGE_FORMAT, DEFAULT_ACCESSLOG_MESSAGE_FORMAT );
84 private final String _messageFormatSeparator = AppPropertiesService.getProperty( PROPERTY_ACCESSLOG_MESSAGE_FORMAT_SEPARATOR,
85 DEFAULT_ACCESSLOG_MESSAGE_FORMAT_SEPARATOR );
86
87 public static final String DEFAULT_LOGGER_ACCESS_LOG = "lutece.accessLogger";
88 private static Logger _defaultLogger = LogManager.getLogger( DEFAULT_LOGGER_ACCESS_LOG );
89
90
91
92
93 @Override
94 public void info( String strEventType, String strAppEventCode, User connectedUser, Object data, String specificOrigin )
95 {
96 Logger logger = getLogger( specificOrigin );
97
98 if ( logger.isInfoEnabled( ) )
99 {
100 String strAppId = AppPropertiesService.getProperty( AccessLoggerConstants.PROPERTY_SITE_CODE, "?" );
101 String logMessage = getLogMessage( strAppId, strEventType, strAppEventCode, ( connectedUser != null ? connectedUser.getAccessCode( ) : "null" ),
102 data );
103
104 logger.info( logMessage );
105 }
106 }
107
108
109
110
111 @Override
112 public void debug( String strEventType, String strAppEventCode, User connectedUser, Object data, String specificOrigin )
113 {
114 Logger logger = getLogger( specificOrigin );
115
116 if ( logger.isDebugEnabled( ) )
117 {
118 String strAppId = AppPropertiesService.getProperty( AccessLoggerConstants.PROPERTY_SITE_CODE, "?" );
119 String logMessage = getLogMessage( strAppId, strEventType, strAppEventCode, ( connectedUser != null ? connectedUser.getAccessCode( ) : "null" ),
120 data );
121
122 logger.debug( logMessage );
123 }
124 }
125
126
127
128
129 @Override
130 public void trace( String strEventType, String strAppEventCode, User connectedUser, Object data, String specificOrigin )
131 {
132 Logger logger = getLogger( specificOrigin );
133
134 if ( logger.isTraceEnabled( ) )
135 {
136 String strAppId = AppPropertiesService.getProperty( AccessLoggerConstants.PROPERTY_SITE_CODE, "?" );
137 String logMessage = getLogMessage( strAppId, strEventType, strAppEventCode, ( connectedUser != null ? connectedUser.getAccessCode( ) : "null" ),
138 data );
139
140 logger.trace( logMessage );
141 }
142 }
143
144
145
146
147 @Override
148 public void warn( String strEventType, String strAppEventCode, User connectedUser, Object data, String specificOrigin )
149 {
150 Logger logger = getLogger( specificOrigin );
151
152 if ( logger.isEnabled( Level.WARN ) )
153 {
154 String strAppId = AppPropertiesService.getProperty( AccessLoggerConstants.PROPERTY_SITE_CODE, "?" );
155 String logMessage = getLogMessage( strAppId, strEventType, strAppEventCode, ( connectedUser != null ? connectedUser.getAccessCode( ) : "null" ),
156 data );
157
158 logger.warn( logMessage );
159 }
160 }
161
162
163
164
165
166
167
168
169
170
171 private String getLogMessage( String strAppId, String strEventType, String strAppEventCode, String strConnectedUserLogin, Object data )
172 {
173
174 String jsonData = "";
175
176 if ( data != null )
177 {
178 ObjectMapper obj = new ObjectMapper( );
179
180 try
181 {
182 jsonData = obj.writeValueAsString( data );
183 }
184 catch( JsonProcessingException e )
185 {
186 jsonData = ERROR_MSG;
187 }
188 }
189
190 return getLogMessage( strAppId, strEventType, strAppEventCode, strConnectedUserLogin, jsonData, isAddHashToLogs( ) );
191 }
192
193
194
195
196
197
198
199
200
201
202 private String getLogMessage( String strAppId, String strEventType, String strAppEventCode, String strConnectedUserLogin, String strData,
203 boolean isAddHashToLogs )
204 {
205
206 String strHash = "";
207
208 if ( isAddHashToLogs )
209 {
210 strHash = getHash( MessageFormat.format( _messageFormat, "", strAppId, strEventType, strAppEventCode, strConnectedUserLogin, strData ) );
211 }
212
213 return MessageFormat.format( _messageFormat, strHash, strAppId, strEventType, strAppEventCode, strConnectedUserLogin, strData );
214 }
215
216
217
218
219
220
221
222
223
224
225 private static String getHash( String message )
226 {
227
228 byte [ ] byteChaine;
229 try
230 {
231 byteChaine = message.getBytes( CONSTANT_HASH_ENCODING );
232 MessageDigest md = MessageDigest.getInstance( CONSTANT_HASH_DIGEST );
233 byte [ ] hash = md.digest( byteChaine );
234
235
236 StringBuilder sb = new StringBuilder( 2 * hash.length );
237 for ( byte b : hash )
238 {
239 sb.append( String.format( "%02x", b & 0xff ) );
240 }
241
242 return sb.toString( );
243
244 }
245 catch( NoSuchAlgorithmException e )
246 {
247 return "Hash ERROR : " + e.getLocalizedMessage( );
248 }
249
250 }
251
252
253
254
255
256
257
258
259 public boolean verifyMessageHash( String message )
260 {
261 try
262 {
263
264 int idx = message.indexOf( _messageFormatSeparator, message.indexOf( DEFAULT_LOGGER_ACCESS_LOG ) );
265
266 String hash = message.substring( idx + 1, idx + CONSTANT_HASH_CHARACTERS_COUNT + 1 );
267
268 String data = "||" + message.substring( idx + CONSTANT_HASH_CHARACTERS_COUNT + 2 );
269
270 return ( hash != null && ( hash.equals( "" ) || hash.equals( getHash( data ) ) ) );
271
272 }
273 catch( StringIndexOutOfBoundsException e )
274 {
275
276 return false;
277 }
278 }
279
280
281
282
283
284
285 public boolean isAddHashToLogs( )
286 {
287 return _bAddHashToLogs;
288 }
289
290
291
292
293
294
295
296 private Logger getLogger( String specificOrigin )
297 {
298 if ( specificOrigin != null && !"".equals( specificOrigin ) )
299 {
300 return LogManager.getLogger( DEFAULT_LOGGER_ACCESS_LOG + "." + specificOrigin );
301 }
302
303 return _defaultLogger;
304
305 }
306 }