Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2010-2013 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.jersey.client.filter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.internal.LocalizationMessages;
import org.glassfish.jersey.internal.util.PropertiesHelper;
/**
* Client filter providing HTTP Digest Authentication with preemptive
* authentication support.
*
* This filter is the main class that adds a support for Http Digest Authentication on the client.
* In order to use this filter, create an instance of the filter and register it to the {@link Client client}.
*
*
* Example:
*
* // create a filter instance and initiate it with username and password
* final HttpDigestAuthFilter digestFilter = new HttpDigestAuthFilter("adam", "pwd87654");
*
* // register the filter into the client (in this case using ClientBuilder)
* Client client = ClientBuilder.newBuilder().register(digestFilter).build();
*
* // make request (authentication will be managed by filter during the request if needed)
* final Response response = client.target("http://example.com/users/adam/age").request().get();
*
*
*
* Filter firstly tries to perform request without authentication. If authentication is needed and
* 401 status code is returned, filter use information from {@code WWW-Authenticate} header to
* construct the digest header and retries the request with {@code Authentication} header. The
* {@code Authentication} header will be stored for the current URI and used next time with {@code nonce}
* value increased (if nonce is defined). The number of cached URIs can be defined by a
* property {@link ClientProperties#DIGESTAUTH_URI_CACHE_SIZELIMIT}.
*
*
*
* Note: The filter must be registered only into the {@code Client}. Filter will not work
* correctly when it is registered to {@link WebTarget}, {@link Invocation.Builder} or
* {@link Invocation}.
*
*
* @author [email protected]
* @author Stefan Katerkamp ([email protected])
* @since 2.3
*/
@Provider
public class HttpDigestAuthFilter implements ClientRequestFilter, ClientResponseFilter {
@Inject
private Configuration config;
private static final Logger logger = Logger.getLogger(HttpDigestAuthFilter.class.getName());
private static final Charset CHARACTER_SET = Charset.forName("iso-8859-1");
private static final String HEADER_DIGEST_SCHEME = "jersey-digest-filter-digest-scheme";
private static final char[] HEX_ARRAY = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
private static final Pattern KEY_VALUE_PAIR_PATTERN = Pattern.compile("(\\w+)\\s*=\\s*(\"([^\"]+)\"|(\\w+))\\s*,?\\s*");
private static final int CLIENT_NONCE_BYTE_COUNT = 4;
private static final int MAXIMUM_DIGEST_CACHE_SIZE = 1000;
private final SecureRandom randomGenerator;
private final String username;
private final byte[] password;
private final Map digestCache;
/**
* Create a new HTTP Basic Authentication filter using provided {@code username}
* and {@code password} string credentials. The string {@code password} will be internally
* stored as a byte array, so that using this constructor does introduce the security risk
* of keeping password as a reference to {@code String}.
*
* @param username user name
* @param password password
*/
public HttpDigestAuthFilter(String username, String password) {
this(username, (password != null) ? password.getBytes(CHARACTER_SET) : new byte[0]);
}
/**
* Create a new HTTP Basic Authentication filter using provided {@code username}
* and {@code password} credentials.
*
* @param username user name
* @param password password byte array
*/
private HttpDigestAuthFilter(String username, byte[] password) {
if (username == null) {
username = "";
}
if (password == null) {
password = new byte[0];
}
this.username = username;
this.password = password;
// TODO: Clean up null check of field config. This is a workaround for a bug
// which leaves filter instances without injection.
// See issue https://java.net/jira/browse/JERSEY-2067
int limit = MAXIMUM_DIGEST_CACHE_SIZE;
if (config != null) {
limit = PropertiesHelper.getValue(config.getProperties(),
ClientProperties.DIGESTAUTH_URI_CACHE_SIZELIMIT, MAXIMUM_DIGEST_CACHE_SIZE);
if (limit < 1) {
limit = MAXIMUM_DIGEST_CACHE_SIZE;
}
}
final int mapSize = limit;
digestCache = Collections.synchronizedMap(
new LinkedHashMap(mapSize) {
// use id as it is an anonymous inner class with changed behaviour
private static final long serialVersionUID = 2546245625L;
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > mapSize;
}
});
try {
randomGenerator = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
throw new ProcessingException(LocalizationMessages.ERROR_DIGEST_FILTER_GENERATOR(), e);
}
}
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
final List