All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
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.
clime.messadmin.admin.HTTPAuthorizationProvider Maven / Gradle / Ivy
Go to download
Notification system and Session administration for J2EE Web Applications
package clime.messadmin.admin;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* NOTE: the Base64 implementation come from Jakarta commons Codec 1.3.
*
* @author Cédrik LIME
*/
class HTTPAuthorizationProvider {
/**
* Byte used to pad output of Base64 data.
*/
private static final byte PAD = (byte) '=';
// Create arrays to hold the base64 characters and a lookup for base64 chars
private static byte[] base64Alphabet = new byte[255];
// private static byte[] lookUpBase64Alphabet = new byte[64];
// Populating the lookup and character arrays
static {
Arrays.fill(base64Alphabet, (byte)-1);
for (int i = 'Z'; i >= 'A'; --i) {
base64Alphabet[i] = (byte) (i - 'A');
}
for (int i = 'z'; i >= 'a'; --i) {
base64Alphabet[i] = (byte) (i - 'a' + 26);
}
for (int i = '9'; i >= '0'; --i) {
base64Alphabet[i] = (byte) (i - '0' + 52);
}
base64Alphabet['+'] = 62;
base64Alphabet['/'] = 63;
// for (int i = 0; i <= 25; ++i) {
// lookUpBase64Alphabet[i] = (byte) ('A' + i);
// }
// for (int i = 26, j = 0; i <= 51; ++i, ++j) {
// lookUpBase64Alphabet[i] = (byte) ('a' + j);
// }
// for (int i = 52, j = 0; i <= 61; ++i, ++j) {
// lookUpBase64Alphabet[i] = (byte) ('0' + j);
// }
// lookUpBase64Alphabet[62] = (byte) '+';
// lookUpBase64Alphabet[63] = (byte) '/';
}
/**
* Encodes binary data using the base64 algorithm but
* does not chunk the output.
*
* @param binaryData Array containing binary data to encode.
* @return Base64-encoded data.
*/
// private static byte[] encodeBase64(byte[] binaryData) {
// /** Used to test the sign of a byte. */
// final int SIGN = -128;
//
// int lengthDataBits = binaryData.length * 8;//EIGHTBIT
// int fewerThan24bits = lengthDataBits % 24;//TWENTYFOURBITGROUP
// int numberTriplets = lengthDataBits / 24;//TWENTYFOURBITGROUP
// byte encodedData[] = null;
// int encodedDataLength = 0;
//
// if (fewerThan24bits != 0) {
// //data not divisible by 24 bit
// encodedDataLength = (numberTriplets + 1) * 4;
// } else {
// // 16 or 8 bit
// encodedDataLength = numberTriplets * 4;
// }
//
// encodedData = new byte[encodedDataLength];
//
// byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
//
// int encodedIndex = 0;
// int dataIndex = 0;
// int i = 0;
//
// //log.debug("number of triplets = " + numberTriplets);
// for (i = 0; i < numberTriplets; ++i) {
// dataIndex = i * 3;
// b1 = binaryData[dataIndex];
// b2 = binaryData[dataIndex + 1];
// b3 = binaryData[dataIndex + 2];
//
// //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
//
// l = (byte) (b2 & 0x0f);
// k = (byte) (b1 & 0x03);
//
// byte val1 =
// ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
// byte val2 =
// ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
// byte val3 =
// ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
//
// encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
// //log.debug( "val2 = " + val2 );
// //log.debug( "k4 = " + (k<<4) );
// //log.debug( "vak = " + (val2 | (k<<4)) );
// encodedData[encodedIndex + 1] =
// lookUpBase64Alphabet[val2 | (k << 4)];
// encodedData[encodedIndex + 2] =
// lookUpBase64Alphabet[(l << 2) | val3];
// encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f];
//
// encodedIndex += 4;
// }
//
// // form integral number of 6-bit groups
// dataIndex = i * 3;
//
// if (fewerThan24bits == 8) {//EIGHTBIT
// b1 = binaryData[dataIndex];
// k = (byte) (b1 & 0x03);
// //log.debug("b1=" + b1);
// //log.debug("b1<<2 = " + (b1>>2) );
// byte val1 =
// ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
// encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
// encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4];
// encodedData[encodedIndex + 2] = PAD;
// encodedData[encodedIndex + 3] = PAD;
// } else if (fewerThan24bits == 16) {//SIXTEENBIT
//
// b1 = binaryData[dataIndex];
// b2 = binaryData[dataIndex + 1];
// l = (byte) (b2 & 0x0f);
// k = (byte) (b1 & 0x03);
//
// byte val1 =
// ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
// byte val2 =
// ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
//
// encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
// encodedData[encodedIndex + 1] =
// lookUpBase64Alphabet[val2 | (k << 4)];
// encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
// encodedData[encodedIndex + 3] = PAD;
// }
//
// return encodedData;
// }
/**
* Decodes Base64 data into octects
*
* @param base64Data Byte array containing Base64 data
* @return Array containing decoded data.
*/
private static byte[] decodeBase64(byte[] base64Data) {
// RFC 2045 requires that we discard ALL non-Base64 characters
base64Data = discardNonBase64(base64Data);
// handle the edge case, so we don't have to worry about it later
if (base64Data.length == 0) {
return new byte[0];
}
int numberQuadruple = base64Data.length / 4;//FOURBYTE
byte decodedData[] = null;
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
// Throw away anything not in base64Data
int encodedIndex = 0;
int dataIndex = 0;
{
// this sizes the output array properly - rlw
int lastData = base64Data.length;
// ignore the '=' padding
while (base64Data[lastData - 1] == PAD) {
if (--lastData == 0) {
return new byte[0];
}
}
decodedData = new byte[lastData - numberQuadruple];
}
for (int i = 0; i < numberQuadruple; ++i) {
dataIndex = i * 4;
marker0 = base64Data[dataIndex + 2];
marker1 = base64Data[dataIndex + 3];
b1 = base64Alphabet[base64Data[dataIndex]];
b2 = base64Alphabet[base64Data[dataIndex + 1]];
if (marker0 != PAD && marker1 != PAD) {
//No PAD e.g 3cQl
b3 = base64Alphabet[marker0];
b4 = base64Alphabet[marker1];
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex + 1] =
(byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
} else if (marker0 == PAD) {
//Two PAD e.g. 3c[Pad][Pad]
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
} else if (marker1 == PAD) {
//One PAD e.g. 3cQ[Pad]
b3 = base64Alphabet[marker0];
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex + 1] =
(byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
}
encodedIndex += 3;
}
return decodedData;
}
/**
* Discards any characters outside of the base64 alphabet, per
* the requirements on page 25 of RFC 2045 - "Any characters
* outside of the base64 alphabet are to be ignored in base64
* encoded data."
*
* @param data The base-64 encoded data to groom
* @return The data, less non-base64 characters (see RFC 2045).
*/
private static byte[] discardNonBase64(byte[] data) {
byte groomedData[] = new byte[data.length];
int bytesCopied = 0;
for (int i = 0; i < data.length; ++i) {
if (isBase64(data[i])) {
groomedData[bytesCopied++] = data[i];
}
}
byte packedData[] = new byte[bytesCopied];
System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
return packedData;
}
private static final boolean isBase64(byte octect) {
if (octect == PAD) {
return true;
} else {
return base64Alphabet[octect] != -1;
}
}
private static String md5(String message) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");//$NON-NLS-1$
byte[] md5 = md.digest(message.getBytes());
return new String(md5);
} catch (NoSuchAlgorithmException nsae) {
throw new RuntimeException("Error while computing md5 hash: " + nsae.getLocalizedMessage());
}
}
public static boolean checkAccess(final String authorizationPassword, HttpServletRequest request, HttpServletResponse response) throws IOException {
// no password set => no authorization required
if (authorizationPassword == null || "".equals(authorizationPassword.trim())) {
return true;
}
// password from a previously-set authorization cookie?
if (request.getCookies() != null) {
Cookie[] cookies = request.getCookies();
String authorizationPasswordHash = md5(authorizationPassword);
// some browsers always set null for cookie.getPath()...
String cookieName = "MessAdmin" + request.getContextPath();//$NON-NLS-1$
for (int i = 0; i < cookies.length; ++i) {
Cookie cookie = cookies[i];
if (cookieName.equals(cookie.getName())) {
String providedPasswordHash = cookie.getValue();
if (authorizationPasswordHash.equals(providedPasswordHash)) {
return true;
}
}
}
}
// we must authenticate the user before letting her play with us
String providedPassword = null;
if (request.getParameter("password") != null) {//$NON-NLS-1$
// password in URL
providedPassword = request.getParameter("password");//$NON-NLS-1$
//request.setAttribute("password", providedPassword);//$NON-NLS-1$
} else if (request.getHeader("Authorization") != null) {//$NON-NLS-1$
// password from HTTP Access Authentication
String authorization = request.getHeader("Authorization");//$NON-NLS-1$
if (! authorization.startsWith("Basic ")) {//$NON-NLS-1$
//TODO we should use "Digest" instead of "Basic", but it is more complicated to code...
throw new IllegalArgumentException("Only Basic HTTP Access Authentication supported");
}
String base64UserPass = authorization.substring("Basic ".length()).trim();//$NON-NLS-1$
String userPass = new String(decodeBase64(base64UserPass.getBytes()));
int index = userPass.indexOf(':');
//String user = userPass.substring(0, index);
String password = userPass.substring(index+1);
providedPassword = password;
} else {
providedPassword = null;
}
if (authorizationPassword.equals(providedPassword)) {
// set authorization Cookie
// some browsers always set null for cookie.getPath()...
String cookieName = "MessAdmin" + request.getContextPath();//$NON-NLS-1$
Cookie cookie = new Cookie(cookieName, md5(authorizationPassword));
cookie.setVersion(1);
cookie.setMaxAge(-1);
cookie.setPath(request.getContextPath());
response.addCookie(cookie);
return true;
} else {
// request Authorization Password
//TODO we should use "Digest" instead of "Basic", but it is more complicated to code...
response.setHeader("WWW-Authenticate", "Basic realm=\"MessAdmin Administration for " + request.getContextPath() + '"');//$NON-NLS-1$ //$NON-NLS-2$
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
}
}