Initial implementation of digest auth page
This commit is contained in:
parent
94fecc0567
commit
c4efab0609
5 changed files with 145 additions and 8 deletions
|
|
@ -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>();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
63
src/zutil/net/http/page/HttpDigestAuthPage.java
Executable file
63
src/zutil/net/http/page/HttpDigestAuthPage.java
Executable 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;
|
||||||
|
}
|
||||||
73
test/zutil/net/http/page/HttpDigestAuthPageTest.java
Executable file
73
test/zutil/net/http/page/HttpDigestAuthPageTest.java
Executable 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue