Add part of client authorization

This commit is contained in:
2025-12-04 21:44:50 +01:00
parent 57370fc96b
commit 6e07688d8b
6 changed files with 94 additions and 25 deletions

View File

@@ -4,6 +4,6 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Intercept {
String allowedMethods() default "GET";
public @interface AllowedVerb {
String name() default "GET";
}

View File

@@ -0,0 +1,11 @@
package httpsServer.httpServer.src.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnlyAuthorizedClients {
}

View File

@@ -0,0 +1,9 @@
package httpsServer.httpServer.src.exceptions;
public class ClientAuthorisationException extends Exception {
public ClientAuthorisationException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,9 @@
package httpsServer.httpServer.src.exceptions;
public class NoSuchVerbException extends Exception {
public NoSuchVerbException(String message) {
super(message);
}
}

View File

@@ -4,7 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.net.httpserver.HttpExchange;
import common.common.src.html.HtmlManager;
import common.common.src.logger.Logger;
import httpsServer.httpServer.src.annotations.Intercept;
import httpsServer.httpServer.src.annotations.AllowedVerb;
import httpsServer.httpServer.src.annotations.OnlyAuthorizedClients;
import httpsServer.httpServer.src.authorization.AuthorizedClients;
import httpsServer.httpServer.src.authorization.Client;
@@ -15,7 +16,7 @@ public class RequestHandler implements IRequestHandler {
final AuthorizedClients authorizedClients = new AuthorizedClients();
@Intercept(allowedMethods = "GET")
@AllowedVerb(name = "GET")
public void handleRoot(HttpExchange exchange) {
try{
respondToGet(exchange, "./assets/pages/index.html");
@@ -24,7 +25,8 @@ public class RequestHandler implements IRequestHandler {
}
}
@Intercept(allowedMethods = "GET")
@AllowedVerb(name = "GET")
@OnlyAuthorizedClients
public void handlePayment(HttpExchange exchange) {
Logger.displayReceived("/payment request");
try{
@@ -34,7 +36,7 @@ public class RequestHandler implements IRequestHandler {
}
}
@Intercept(allowedMethods = "POST")
@AllowedVerb(name = "POST")
public void handleLogin(HttpExchange exchange) {
try {
InputStream is = exchange.getRequestBody();
@@ -58,6 +60,7 @@ public class RequestHandler implements IRequestHandler {
e.printStackTrace();
}
}
private void respondToGet(HttpExchange exchange, String pagePath) throws IOException {
try{

View File

@@ -1,45 +1,82 @@
package httpsServer.httpServer.src.interceptors;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.net.httpserver.HttpExchange;
import common.common.src.logger.Logger;
import httpsServer.httpServer.src.annotations.Intercept;
import httpsServer.httpServer.src.annotations.AllowedVerb;
import httpsServer.httpServer.src.annotations.OnlyAuthorizedClients;
import httpsServer.httpServer.src.authorization.AuthorizedClients;
import httpsServer.httpServer.src.authorization.Client;
import httpsServer.httpServer.src.exceptions.NoSuchVerbException;
import httpsServer.httpServer.src.exceptions.ClientAuthorisationException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.*;
import java.nio.Buffer;
import java.nio.charset.StandardCharsets;
public class RequestInterceptor implements InvocationHandler {
private final AuthorizedClients authorizedClients;
private final ObjectMapper mapper;
private final Object target;
public RequestInterceptor(Object target) {
authorizedClients = new AuthorizedClients();
mapper = new ObjectMapper();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
HttpExchange exchange = (HttpExchange) args[0];
try{
Method realMethod = target.getClass().getMethod(method.getName(), method.getParameterTypes());
Method realMethod = target.getClass().getMethod(method.getName(), method.getParameterTypes());
if (!realMethod.isAnnotationPresent(Intercept.class)) return null;
checkAuthorizedVerb(realMethod, exchange.getRequestMethod());
//String a = exchange.getRequestHeaders().getFirst("Header-Name");
checkAuthorizedClient(realMethod, exchange.getRequestBody());
Logger.displayReceived("/ request");
HttpExchange exchange = (HttpExchange)args[0];
Intercept annotation = realMethod.getAnnotation(Intercept.class);
String allowedVerb = annotation.allowedMethods();
String receivedVerb = exchange.getRequestMethod();
if(isAuthorizedVerb(allowedVerb, receivedVerb)) {
return method.invoke(target, args);
} else {
exchange.sendResponseHeaders(405, -1);
exchange.getResponseBody().close();
} catch (NoSuchVerbException e) {
closeExchangeWithCode(exchange, 405);
return null;
} catch (ClientAuthorisationException e) {
closeExchangeWithCode(exchange, 401);
return null;
}
}
private boolean isAuthorizedVerb(String baseVerb, String receivedVerb) {
return baseVerb.equalsIgnoreCase(receivedVerb);
private void closeExchangeWithCode(HttpExchange exchange, int httpCode) throws IOException {
exchange.sendResponseHeaders(httpCode, -1);
exchange.getResponseBody().close();
}
private void checkAuthorizedVerb(Method method, String receivedVerb) throws NoSuchVerbException {
if (!method.isAnnotationPresent(AllowedVerb.class)) return;
String allowedVerb = method.getAnnotation(AllowedVerb.class).name();
if(!allowedVerb.equalsIgnoreCase(receivedVerb)){
throw new NoSuchVerbException("HTTP verb not allowed");
}
}
private void checkAuthorizedClient(Method method, InputStream data) throws ClientAuthorisationException {
if (!method.isAnnotationPresent(OnlyAuthorizedClients.class)) return;
Client client = null;
try(BufferedReader reader = new BufferedReader(new InputStreamReader(data, StandardCharsets.UTF_8))){
String body = reader.lines().reduce("", (acc, line) -> acc + line + "\n");
client = mapper.readValue(body, Client.class);
} catch (IOException e){
throw new ClientAuthorisationException("Unable to read body");
}
if(!authorizedClients.isAuthorized(client)){
throw new ClientAuthorisationException("Client not authorized");
}
}
}