Skip to content

Commit df6faf0

Browse files
author
jxiaobin
committed
hide password in payload log
1 parent 5133451 commit df6faf0

File tree

5 files changed

+601
-8
lines changed

5 files changed

+601
-8
lines changed

openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyConnector.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.List;
44
import java.util.Map;
5+
import java.util.logging.Logger;
56

67
import javax.ws.rs.core.MultivaluedMap;
78
import javax.ws.rs.ext.ContextResolver;
@@ -20,7 +21,6 @@
2021
import com.sun.jersey.api.client.WebResource;
2122
import com.sun.jersey.api.client.config.ClientConfig;
2223
import com.sun.jersey.api.client.config.DefaultClientConfig;
23-
import com.sun.jersey.api.client.filter.LoggingFilter;
2424
import com.sun.jersey.client.impl.ClientRequestImpl;
2525
import com.sun.jersey.core.header.OutBoundHeaders;
2626
import com.woorea.openstack.base.client.OpenStackClientConnector;
@@ -31,6 +31,8 @@
3131
public class JerseyConnector implements OpenStackClientConnector {
3232

3333
protected Client client = null;
34+
protected boolean logPassword;
35+
private JerseyLoggingFilter logger = new JerseyLoggingFilter(Logger.getLogger("os"));
3436

3537
public JerseyConnector() {
3638
ClientConfig clientConfig = new DefaultClientConfig();
@@ -47,7 +49,7 @@ public <T> OpenStackResponse request(OpenStackRequest<T> request) {
4749
target = target.queryParam(entry.getKey(), String.valueOf(o));
4850
}
4951
}
50-
target.addFilter(new LoggingFilter());
52+
target.addFilter(logger);
5153
MultivaluedMap<String, Object> headers = new OutBoundHeaders();
5254
for(Map.Entry<String, List<Object>> h : request.headers().entrySet()) {
5355
for(Object v : h.getValue()) {
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
/*
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3+
*
4+
* Copyright (c) 2010-2011 Oracle and/or its affiliates. All rights reserved.
5+
*
6+
* The contents of this file are subject to the terms of either the GNU
7+
* General Public License Version 2 only ("GPL") or the Common Development
8+
* and Distribution License("CDDL") (collectively, the "License"). You
9+
* may not use this file except in compliance with the License. You can
10+
* obtain a copy of the License at
11+
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
12+
* or packager/legal/LICENSE.txt. See the License for the specific
13+
* language governing permissions and limitations under the License.
14+
*
15+
* When distributing the software, include this License Header Notice in each
16+
* file and include the License file at packager/legal/LICENSE.txt.
17+
*
18+
* GPL Classpath Exception:
19+
* Oracle designates this particular file as subject to the "Classpath"
20+
* exception as provided by Oracle in the GPL Version 2 section of the License
21+
* file that accompanied this code.
22+
*
23+
* Modifications:
24+
* If applicable, add the following below the License Header, with the fields
25+
* enclosed by brackets [] replaced by your own identifying information:
26+
* "Portions Copyright [year] [name of copyright owner]"
27+
*
28+
* Contributor(s):
29+
* If you wish your version of this file to be governed by only the CDDL or
30+
* only the GPL Version 2, indicate your decision by adding "[Contributor]
31+
* elects to include this software in this distribution under the [CDDL or GPL
32+
* Version 2] license." If you don't indicate a single choice of license, a
33+
* recipient has the option to distribute your version of this file under
34+
* either the CDDL, the GPL Version 2 or to extend the choice of license to
35+
* its licensees as provided above. However, if you add GPL Version 2 code
36+
* and therefore, elected the GPL Version 2 license, then the option applies
37+
* only if the new code is made subject to such option by the copyright
38+
* holder.
39+
*/
40+
package com.woorea.openstack.connector;
41+
42+
import java.io.ByteArrayInputStream;
43+
import java.io.ByteArrayOutputStream;
44+
import java.io.IOException;
45+
import java.io.InputStream;
46+
import java.io.OutputStream;
47+
import java.io.PrintStream;
48+
import java.util.List;
49+
import java.util.Map;
50+
import java.util.logging.Logger;
51+
52+
import javax.ws.rs.core.MultivaluedMap;
53+
54+
import com.sun.jersey.api.client.AbstractClientRequestAdapter;
55+
import com.sun.jersey.api.client.ClientHandlerException;
56+
import com.sun.jersey.api.client.ClientRequest;
57+
import com.sun.jersey.api.client.ClientRequestAdapter;
58+
import com.sun.jersey.api.client.ClientResponse;
59+
import com.sun.jersey.api.client.filter.ClientFilter;
60+
import com.sun.jersey.api.client.filter.LoggingFilter;
61+
import com.sun.jersey.core.util.ReaderWriter;
62+
63+
/**
64+
* A logging filter.
65+
*
66+
*/
67+
public class JerseyLoggingFilter extends ClientFilter {
68+
69+
private static final Logger LOGGER = Logger.getLogger(LoggingFilter.class.getName());
70+
71+
private static final String NOTIFICATION_PREFIX = "* ";
72+
73+
private static final String REQUEST_PREFIX = "> ";
74+
75+
private static final String RESPONSE_PREFIX = "< ";
76+
77+
private static final String PASSWORD_PATTERN = "\"password\".*:.*\"(.*)\"";
78+
79+
private final class Adapter extends AbstractClientRequestAdapter {
80+
private final StringBuilder b;
81+
82+
Adapter(ClientRequestAdapter cra, StringBuilder b) {
83+
super(cra);
84+
this.b = b;
85+
}
86+
87+
public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException {
88+
return new LoggingOutputStream(getAdapter().adapt(request, out), b);
89+
}
90+
91+
}
92+
93+
private final class LoggingOutputStream extends OutputStream {
94+
private final OutputStream out;
95+
96+
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
97+
98+
private final StringBuilder b;
99+
100+
LoggingOutputStream(OutputStream out, StringBuilder b) {
101+
this.out = out;
102+
this.b = b;
103+
}
104+
105+
@Override
106+
public void write(byte[] b) throws IOException {
107+
baos.write(b);
108+
out.write(b);
109+
}
110+
111+
@Override
112+
public void write(byte[] b, int off, int len) throws IOException {
113+
baos.write(b, off, len);
114+
out.write(b, off, len);
115+
}
116+
117+
@Override
118+
public void write(int b) throws IOException {
119+
baos.write(b);
120+
out.write(b);
121+
}
122+
123+
@Override
124+
public void close() throws IOException {
125+
printEntity(b, baos.toByteArray());
126+
log(b);
127+
out.close();
128+
}
129+
}
130+
131+
private final PrintStream loggingStream;
132+
133+
private final Logger logger;
134+
135+
private long _id = 0;
136+
137+
/**
138+
* Create a logging filter logging the request and response to
139+
* a default JDK logger, named as the fully qualified class name of this
140+
* class.
141+
*/
142+
public JerseyLoggingFilter() {
143+
this(LOGGER);
144+
}
145+
146+
/**
147+
* Create a logging filter logging the request and response to
148+
* a JDK logger.
149+
*
150+
* @param logger the logger to log requests and responses.
151+
*/
152+
public JerseyLoggingFilter(Logger logger) {
153+
this.loggingStream = null;
154+
this.logger = logger;
155+
}
156+
157+
/**
158+
* Create a logging filter logging the request and response to
159+
* print stream.
160+
*
161+
* @param loggingStream the print stream to log requests and responses.
162+
*/
163+
public JerseyLoggingFilter(PrintStream loggingStream) {
164+
this.loggingStream = loggingStream;
165+
this.logger = null;
166+
}
167+
168+
private void log(StringBuilder b) {
169+
if (logger != null) {
170+
logger.info(b.toString());
171+
} else {
172+
loggingStream.print(b);
173+
}
174+
}
175+
176+
private StringBuilder prefixId(StringBuilder b, long id) {
177+
b.append(Long.toString(id)).append(" ");
178+
return b;
179+
}
180+
181+
@Override
182+
public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
183+
long id = ++this._id;
184+
185+
logRequest(id, request);
186+
187+
ClientResponse response = getNext().handle(request);
188+
189+
logResponse(id, response);
190+
191+
return response;
192+
}
193+
194+
private void logRequest(long id, ClientRequest request) {
195+
StringBuilder b = new StringBuilder();
196+
197+
printRequestLine(b, id, request);
198+
printRequestHeaders(b, id, request.getHeaders());
199+
200+
if (request.getEntity() != null) {
201+
request.setAdapter(new Adapter(request.getAdapter(), b));
202+
} else {
203+
log(b);
204+
}
205+
}
206+
207+
private void printRequestLine(StringBuilder b, long id, ClientRequest request) {
208+
prefixId(b, id).append(NOTIFICATION_PREFIX).append("Client out-bound request").append("\n");
209+
prefixId(b, id).append(REQUEST_PREFIX).append(request.getMethod()).append(" ").
210+
append(request.getURI().toASCIIString()).append("\n");
211+
}
212+
213+
private void printRequestHeaders(StringBuilder b, long id, MultivaluedMap<String, Object> headers) {
214+
for (Map.Entry<String, List<Object>> e : headers.entrySet()) {
215+
List<Object> val = e.getValue();
216+
String header = e.getKey();
217+
218+
if(val.size() == 1) {
219+
prefixId(b, id).append(REQUEST_PREFIX).append(header).append(": ").append(ClientRequest.getHeaderValue(val.get(0))).append("\n");
220+
} else {
221+
StringBuilder sb = new StringBuilder();
222+
boolean add = false;
223+
for(Object o : val) {
224+
if(add) sb.append(',');
225+
add = true;
226+
sb.append(ClientRequest.getHeaderValue(o));
227+
}
228+
prefixId(b, id).append(REQUEST_PREFIX).append(header).append(": ").append(sb.toString()).append("\n");
229+
}
230+
}
231+
}
232+
233+
private void logResponse(long id, ClientResponse response) {
234+
StringBuilder b = new StringBuilder();
235+
236+
printResponseLine(b, id, response);
237+
printResponseHeaders(b, id, response.getHeaders());
238+
239+
ByteArrayOutputStream out = new ByteArrayOutputStream();
240+
InputStream in = response.getEntityInputStream();
241+
try {
242+
ReaderWriter.writeTo(in, out);
243+
244+
byte[] requestEntity = out.toByteArray();
245+
printEntity(b, requestEntity);
246+
response.setEntityInputStream(new ByteArrayInputStream(requestEntity));
247+
} catch (IOException ex) {
248+
throw new ClientHandlerException(ex);
249+
}
250+
log(b);
251+
}
252+
253+
private void printResponseLine(StringBuilder b, long id, ClientResponse response) {
254+
prefixId(b, id).append(NOTIFICATION_PREFIX).
255+
append("Client in-bound response").append("\n");
256+
prefixId(b, id).append(RESPONSE_PREFIX).
257+
append(Integer.toString(response.getStatus())).
258+
append("\n");
259+
}
260+
261+
private void printResponseHeaders(StringBuilder b, long id, MultivaluedMap<String, String> headers) {
262+
for (Map.Entry<String, List<String>> e : headers.entrySet()) {
263+
String header = e.getKey();
264+
for (String value : e.getValue()) {
265+
prefixId(b, id).append(RESPONSE_PREFIX).append(header).append(": ").
266+
append(value).append("\n");
267+
}
268+
}
269+
prefixId(b, id).append(RESPONSE_PREFIX).append("\n");
270+
}
271+
272+
private void printEntity(StringBuilder b, byte[] entity) throws IOException {
273+
if (entity.length == 0)
274+
return;
275+
String entityString = new String(entity);
276+
entityString = entityString.replaceAll(PASSWORD_PATTERN, "\"password\" : \"******\"");
277+
b.append(entityString).append("\n");
278+
}
279+
}

openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Connector.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
import javax.ws.rs.client.WebTarget;
1212
import javax.ws.rs.core.MediaType;
1313

14-
import org.glassfish.jersey.filter.LoggingFilter;
15-
1614
import com.woorea.openstack.base.client.HttpMethod;
1715
import com.woorea.openstack.base.client.OpenStackClientConnector;
1816
import com.woorea.openstack.base.client.OpenStackRequest;
@@ -22,6 +20,7 @@
2220
public class JaxRs20Connector implements OpenStackClientConnector {
2321

2422
protected Client client = OpenStack.CLIENT;
23+
private Jersey2LoggingFilter logger = new Jersey2LoggingFilter(Logger.getLogger("os"), 10000);
2524

2625
@Override
2726
public <T> OpenStackResponse request(OpenStackRequest<T> request) {
@@ -32,8 +31,7 @@ public <T> OpenStackResponse request(OpenStackRequest<T> request) {
3231
target = target.queryParam(entry.getKey(), o);
3332
}
3433
}
35-
36-
target.register(new LoggingFilter(Logger.getLogger("os"), 10000));
34+
target.register(logger);
3735
Invocation.Builder invocation = target.request();
3836

3937
for(Map.Entry<String, List<Object>> h : request.headers().entrySet()) {
@@ -62,5 +60,4 @@ public <T> OpenStackResponse request(OpenStackRequest<T> request) {
6260
.getStatusInfo().toString(), e.getResponse().getStatus());
6361
}
6462
}
65-
6663
}

0 commit comments

Comments
 (0)