Initial implementation of digest auth page

This commit is contained in:
Ziver Koc 2016-10-26 17:34:21 +02:00
parent 94fecc0567
commit c4efab0609
5 changed files with 145 additions and 8 deletions

View file

@ -45,7 +45,7 @@ public class HttpHeader {
private HashMap<String, String> cookies; private HashMap<String, String> cookies;
protected HttpHeader(){ public HttpHeader(){
urlAttributes = new HashMap<String, String>(); urlAttributes = new HashMap<String, String>();
headers = new HashMap<String, String>(); headers = new HashMap<String, String>();
cookies = new HashMap<String, String>(); cookies = new HashMap<String, String>();

View file

@ -31,6 +31,7 @@ import zutil.parser.URLDecoder;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -106,7 +107,7 @@ public class HttpHeaderParser {
if( statusLine.startsWith("HTTP/") ){ if( statusLine.startsWith("HTTP/") ){
header.setIsRequest(false); header.setIsRequest(false);
header.setHTTPVersion( Float.parseFloat( statusLine.substring( 5 , 8))); header.setHTTPVersion( Float.parseFloat( statusLine.substring( 5 , 8)));
header.setHTTPCode( Integer.parseInt( statusLine.substring( 9, 12 ))); header.setHTTPCode( Integer.parseInt( statusLine.substring( 9, statusLine.indexOf(' ', 9) )));
} }
// Client Request // Client Request
else if(statusLine.contains("HTTP/")){ else if(statusLine.contains("HTTP/")){
@ -163,12 +164,12 @@ public class HttpHeaderParser {
*/ */
public static void parseHeaderValues(Map<String,String> map, String headerValue, String delimiter){ public static void parseHeaderValues(Map<String,String> map, String headerValue, String delimiter){
if(headerValue != null && !headerValue.isEmpty()){ if(headerValue != null && !headerValue.isEmpty()){
String[] tmp = headerValue.split(delimiter); String[] tmpArr = headerValue.split(delimiter);
for(String cookie : tmp){ for(String cookie : tmpArr){
String[] tmp2 = PATTERN_EQUAL.split(cookie, 2); String[] tmpStr = PATTERN_EQUAL.split(cookie, 2);
map.put( map.put(
tmp2[0].trim(), // Key tmpStr[0].trim(), // Key
StringUtil.trim((tmp2.length>1 ? tmp2[1] : "").trim(), '\"')); //Value StringUtil.trim((tmpStr.length>1 ? tmpStr[1] : "").trim(), '\"')); //Value
} }
} }
} }

View file

@ -86,7 +86,7 @@ public class HttpPrintStream extends OutputStream{
this.out = new PrintStream(out); this.out = new PrintStream(out);
this.httpVersion = "1.1"; this.httpVersion = "1.1";
this.message_type = type; this.message_type = type;
this.res_status_code = 0; this.res_status_code = 200;
this.headers = new HashMap<String, String>(); this.headers = new HashMap<String, String>();
this.cookies = new HashMap<String, String>(); this.cookies = new HashMap<String, String>();
this.buffer = new StringBuffer(); this.buffer = new StringBuffer();

View file

@ -0,0 +1,63 @@
package zutil.net.http.page;
import zutil.net.http.HttpHeader;
import zutil.net.http.HttpPage;
import zutil.net.http.HttpPrintStream;
import java.io.IOException;
import java.util.Map;
/**
* A abstract page that requires HTTP Digest authentication
* to access the subclass HttpPage.
*
* @see <a href="https://tools.ietf.org/html/rfc2617">rfc2617</a>
* @author Ziver
*/
public abstract class HttpDigestAuthPage implements HttpPage{
private static final String HTTP_AUTH_HEADER = "WWW-Authenticate";
private static final String AUTH_TYPE = "Digest";
private static final String AUTH_REALM = "realm";
private static final String AUTH_QUALITY_OF_PROTECTION = "qop";
private static final String AUTH_NONCE = "nonce";
private static final String AUTH_OPAQUE = "opaque";
private static final String AUTH_USERNAME = "username";
private static final String AUTH_URI = "uri";
private static final String AUTH_CNONCE = "cnonce";
private static final String AUTH_RESPONSE = "response";
private String realm;
@Override
public final void respond(HttpPrintStream out,
HttpHeader headers,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) throws IOException {
out.setStatusCode(401);
out.setHeader(HTTP_AUTH_HEADER, generateAuthHeader());
}
private String generateAuthHeader(){
StringBuilder str = new StringBuilder();
str.append(AUTH_TYPE).append(' ');
str.append(AUTH_REALM).append("=\"").append("ll").append("\", ");
str.append(AUTH_QUALITY_OF_PROTECTION).append("=\"").append("ll").append("\", ");
str.append(AUTH_NONCE).append("=\"").append("ll").append("\", ");
str.append(AUTH_OPAQUE).append("=\"").append("ll").append("\"");
return str.toString();
}
public abstract void authRespond(HttpPrintStream out,
HttpHeader headers,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) throws IOException;
}

View file

@ -0,0 +1,73 @@
package zutil.net.http.page;
import org.junit.Test;
import zutil.io.StringOutputStream;
import zutil.net.http.HttpHeader;
import zutil.net.http.HttpHeaderParser;
import zutil.net.http.HttpPrintStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.*;
/**
* @author Ziver on 2016-10-26.
*/
public class HttpDigestAuthPageTest {
private static final String PAGE_CONTENT = "Hello World!";
@Test
public void cleanRequest() throws IOException {
HttpHeader header = new HttpHeader();
HttpHeader output = makeRequest(header);
assertEquals(401, output.getHTTPCode());
assertTrue(output.getHeader("WWW-Authenticate") != null);
assertEquals("Digest", parseAuthType(output));
Map<String,String> authHeader = parseAuthHeader(output);
assertTrue(authHeader.containsKey("realm"));
assertTrue(authHeader.containsKey("qop"));
assertTrue(authHeader.containsKey("nonce"));
assertTrue(authHeader.containsKey("opaque"));
}
public static HttpHeader makeRequest(HttpHeader headers) throws IOException {
StringOutputStream buff = new StringOutputStream();
HttpPrintStream out = new HttpPrintStream(buff);
new HttpDigestTestPage().respond(
out, headers, new HashMap(), new HashMap(), new HashMap());
out.flush();
HttpHeaderParser parser = new HttpHeaderParser(buff.toString());
return parser.read();
}
public static String parseAuthType(HttpHeader headers){
String tmp = headers.getHeader("WWW-Authenticate");
return tmp.substring(0, tmp.indexOf(' '));
}
public static HashMap<String,String> parseAuthHeader(HttpHeader headers){
HashMap<String,String> authHeaders = new HashMap<>();
String tmp = headers.getHeader("WWW-Authenticate");
HttpHeaderParser.parseHeaderValues(authHeaders,
tmp.substring(tmp.indexOf(' ')+1),
",");
return authHeaders;
}
private static class HttpDigestTestPage extends HttpDigestAuthPage{
@Override
public void authRespond(HttpPrintStream out,
HttpHeader headers,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) throws IOException {
out.print(PAGE_CONTENT);
}
}
}