added security to picture upload resource

This commit is contained in:
verboomp
2026-01-20 15:28:15 +01:00
parent 8ccd98755b
commit 39580438c2
5 changed files with 157 additions and 6 deletions

View File

@@ -0,0 +1,116 @@
package marketing.heyday.hartmann.fotodocumentation.core.utils;
import java.nio.charset.Charset;
import java.security.Principal;
import java.util.Optional;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wildfly.security.auth.principal.NamePrincipal;
import org.wildfly.security.auth.server.RealmUnavailableException;
import org.wildfly.security.auth.server.SecurityDomain;
import org.wildfly.security.auth.server.SecurityIdentity;
import org.wildfly.security.evidence.PasswordGuessEvidence;
import jakarta.servlet.http.HttpServletRequest;
import javaslang.Tuple;
import javaslang.Tuple2;
/**
*
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: heyday Marketing GmbH</p>
* @author <a href="mailto:p.verboom@heyday.marketing">Patrick Verboom</a>
* @version 1.0
*
* created: 20 Jan 2026
*/
public class LoginUtils {
private static final Log LOG = LogFactory.getLog(LoginUtils.class);
private static final int BASIC_HEADER_SIZE = 6;
private static final int USERPASS_LENGTH = 1;
public Optional<SecurityIdentity> authenticate(HttpServletRequest httpServletRequest) {
Tuple2<String, String> userPass = extractUsernamePassword(httpServletRequest);
if (userPass._1.isBlank() || userPass._2.isBlank()) {
return Optional.empty();
}
return authenticate(userPass._1, userPass._2);
}
public Optional<String> getSecurityToken(HttpServletRequest httpServletRequest) {
Optional<String[]> headerOpt = extractAuthHeader(httpServletRequest);
if (headerOpt.isPresent() && headerOpt.get().length > 2) {
return Optional.ofNullable(headerOpt.get()[2]);
}
return Optional.empty();
}
private Optional<SecurityIdentity> authenticate(String username, String password) {
try {
Principal principal = new NamePrincipal(username);
PasswordGuessEvidence evidence = new PasswordGuessEvidence(password.toCharArray());
SecurityDomain sd = SecurityDomain.getCurrent();
return Optional.ofNullable(sd.authenticate(principal, evidence));
} catch (RealmUnavailableException | SecurityException e) {
LOG.warn("Failed to authenticate user " + e.getMessage(), e);
return Optional.empty();
}
}
private Tuple2<String, String> extractUsernamePassword(HttpServletRequest httpServletRequest) {
Optional<String[]> userPassOptional = extractAuthHeader(httpServletRequest);
if (userPassOptional.isPresent() && userPassOptional.get().length >= USERPASS_LENGTH) {
String[] userpass = userPassOptional.get();
String username = userpass[0];
String password = userpass.length > USERPASS_LENGTH ? userpass[1] : "";
return Tuple.of(username, password);
}
return Tuple.of("", "");
}
private Optional<String[]> extractAuthHeader(HttpServletRequest httpServletRequest) {
Optional<String[]> retVal = Optional.empty();
String authorization = httpServletRequest.getHeader("Authorization");
if (authorization != null && StringUtils.length(authorization) > BASIC_HEADER_SIZE) {
authorization = authorization.substring(BASIC_HEADER_SIZE);
String decoded = StringUtils.toEncodedString(Base64.decodeBase64(authorization), Charset.forName("utf-8"));
retVal = Optional.of(decoded.split(":"));
}
return retVal;
}
/**
* Extract device information from User-Agent header
*
* @param request HTTP servlet request
* @return Device/browser information
*/
public String extractDeviceInfo(HttpServletRequest request) {
String userAgent = request.getHeader("User-Agent");
return userAgent != null ? userAgent : "Unknown";
}
/**
* Extract client IP address, considering proxies
*
* @param request HTTP servlet request
* @return Client IP address
*/
public String extractIpAddress(HttpServletRequest request) {
String xForwardedFor = request.getHeader("X-Forwarded-For");
if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
// X-Forwarded-For can contain multiple IPs, take the first one
return xForwardedFor.split(",")[0].trim();
}
return request.getRemoteAddr();
}
}

View File

@@ -1,18 +1,27 @@
package marketing.heyday.hartmann.fotodocumentation.rest;
import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.resteasy.annotations.GZIP;
import org.wildfly.security.auth.server.SecurityIdentity;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.ejb.EJB;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import marketing.heyday.hartmann.fotodocumentation.core.service.CustomerPictureService;
import marketing.heyday.hartmann.fotodocumentation.core.utils.LoginUtils;
import marketing.heyday.hartmann.fotodocumentation.rest.jackson.JsonSchemaValidate;
import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerPictureValue;
@@ -28,18 +37,28 @@ import marketing.heyday.hartmann.fotodocumentation.rest.vo.CustomerPictureValue;
@RequestScoped
@Path("customer-picture")
public class CustomerPictureResource {
private static final Log LOG = LogFactory.getLog(CustomerPictureResource.class);
@EJB
private CustomerPictureService customerPictureService;
@Inject
private LoginUtils loginUtils;
@GZIP
@POST
@Path("")
//@Authenticate(shouldBeInAllRoles = RightUtils.ADMIN_RIGHT)
@Consumes(MediaType.APPLICATION_JSON)
@Operation(summary = "Add Customer Image to database")
@ApiResponse(responseCode = "200", description = "Add successfull")
public Response doAddCustomerPicture(@JsonSchemaValidate("schema/customer_picture_add.json") CustomerPictureValue customerPictureValue) {
public Response doAddCustomerPicture(@Context HttpServletRequest httpServletRequest, @JsonSchemaValidate("schema/customer_picture_add.json") CustomerPictureValue customerPictureValue) {
Optional<SecurityIdentity> identity = loginUtils.authenticate(httpServletRequest);
if (identity.isEmpty()) {
LOG.debug("identity empty login invalid");
return Response.status(401).build();
}
boolean success = customerPictureService.addCustomerPicture(customerPictureValue);
return success ? Response.ok().build() : Response.status(Status.BAD_REQUEST).build();