HTTP Basic Auth

Although not a requested feature to spec, will allow for easy testing of authentication.
This commit is contained in:
michaelpede 2021-04-09 14:41:08 -07:00
parent 4248c59e45
commit ecf0a0938b
4 changed files with 137 additions and 1 deletions

View File

@ -0,0 +1,69 @@
package org.reso.service.security;
import org.reso.service.servlet.RESOservlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Base64;
import java.util.Enumeration;
public class BasicAuthProvider implements Provider
{
public static final String AUTH_STR = "Authorization";
public static final String BASIC_STR = "Basic";
public static final String AUTH_SPACE = " ";
public static final String AUTH_SEP = ":";
public static final String AUTH_USER = "reso";
public static final String AUTH_PASSWORD = "reso-test-password";
private static final Logger LOG = LoggerFactory.getLogger(BasicAuthProvider.class);
/**
* A simple BASIC Auth with static username and password. Purely for testing purposes.
* @param req The HTTP Request object from the servlet.
* @return true if authorized, false otherwise.
*/
@Override public boolean verify(HttpServletRequest req)
{
Enumeration<String> headers = req.getHeaders(BasicAuthProvider.AUTH_STR);
while (headers.hasMoreElements())
{
String authResp = headers.nextElement();
if (authResp!=null && authResp.length()>0)
{
String[] parts = authResp.split(BasicAuthProvider.AUTH_SPACE);
if (parts[0].equals(BasicAuthProvider.BASIC_STR) && parts.length==2)
{
String base64decoded = new String(Base64.getDecoder().decode(parts[1]));
parts = base64decoded.split(BasicAuthProvider.AUTH_SEP);
if (parts.length==2)
{
String username = parts[0];
String password = parts[1];
if (username.equals(AUTH_USER) && password.equals(AUTH_PASSWORD))
{
return true;
}
}
}
}
}
return false;
}
@Override public void unauthorizedResponse(HttpServletResponse resp)
{
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
resp.setHeader("WWW-Authenticate","Basic");
}
}

View File

@ -0,0 +1,12 @@
package org.reso.service.security;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Provider
{
boolean verify(final HttpServletRequest req);
void unauthorizedResponse(final HttpServletResponse resp);
}

View File

@ -0,0 +1,43 @@
package org.reso.service.security;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
public class Validator
{
ArrayList<Provider> providers = new ArrayList<>();
public Validator()
{
}
public void addProvider(Provider provider)
{
providers.add(provider);
}
public boolean verify(HttpServletRequest req)
{
for (Provider provider: this.providers)
{
if (provider.verify(req))
{
return true;
}
}
return false;
}
public boolean unauthorizedResponse(HttpServletResponse resp)
{
if (providers.size()>0)
{
providers.get(0).unauthorizedResponse(resp);
return true;
}
return false;
}
}

View File

@ -9,6 +9,8 @@ import org.reso.service.data.GenericEntityCollectionProcessor;
import org.reso.service.data.definition.LookupDefinition; import org.reso.service.data.definition.LookupDefinition;
import org.reso.service.data.meta.ResourceInfo; import org.reso.service.data.meta.ResourceInfo;
import org.reso.service.edmprovider.RESOedmProvider; import org.reso.service.edmprovider.RESOedmProvider;
import org.reso.service.security.BasicAuthProvider;
import org.reso.service.security.Validator;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -25,6 +27,7 @@ public class RESOservlet extends HttpServlet
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(RESOservlet.class); private static final Logger LOG = LoggerFactory.getLogger(RESOservlet.class);
private Connection connect = null; private Connection connect = null;
private Validator validator = null;
@Override public void init() throws ServletException @Override public void init() throws ServletException
@ -39,6 +42,9 @@ public class RESOservlet extends HttpServlet
); );
} }
this.validator = new Validator();
this.validator.addProvider(new BasicAuthProvider());
String mysqlHost = env.get("SQL_HOST"); String mysqlHost = env.get("SQL_HOST");
String mysqlUser = env.get("SQL_USER"); String mysqlUser = env.get("SQL_USER");
String mysqlPwd = env.get("SQL_PASSWORD"); String mysqlPwd = env.get("SQL_PASSWORD");
@ -60,6 +66,12 @@ public class RESOservlet extends HttpServlet
protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
if (!this.validator.verify(req) && this.validator.unauthorizedResponse(resp))
{ // Due to order of operations, the unauthorized response won't be called unless the verification fails.
resp.getWriter().println("<html><body><p>Unauthorized</p></body></html>");
return;
}
try { try {
// create odata handler and configure it with CsdlEdmProvider and Processor // create odata handler and configure it with CsdlEdmProvider and Processor
OData odata = OData.newInstance(); OData odata = OData.newInstance();