chore: update

This commit is contained in:
TakahashiNg
2026-04-30 15:56:03 +00:00
parent 5de3ad1a1c
commit a8ed99f134
11 changed files with 257 additions and 153 deletions
+14 -13
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8"?>
<project <project
xmlns="http://maven.apache.org/POM/4.0.0" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
> >
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -20,11 +20,9 @@
<compiler-plugin.version>3.15.0</compiler-plugin.version> <compiler-plugin.version>3.15.0</compiler-plugin.version>
<maven.compiler.release>25</maven.compiler.release> <maven.compiler.release>25</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
>UTF-8</project.reporting.outputEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id> <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>3.32.4</quarkus.platform.version> <quarkus.platform.version>3.32.4</quarkus.platform.version>
<skipITs>true</skipITs> <skipITs>true</skipITs>
<surefire-plugin.version>3.5.4</surefire-plugin.version> <surefire-plugin.version>3.5.4</surefire-plugin.version>
@@ -48,6 +46,11 @@
<artifactId>lib</artifactId> <artifactId>lib</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security</artifactId>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>net.datafaker</groupId> <groupId>net.datafaker</groupId>
<artifactId>datafaker</artifactId> <artifactId>datafaker</artifactId>
@@ -138,8 +141,7 @@
<configuration> <configuration>
<argLine>@{argLine}</argLine> <argLine>@{argLine}</argLine>
<systemPropertyVariables> <systemPropertyVariables>
<java.util.logging.manager <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home> <maven.home>${maven.home}</maven.home>
</systemPropertyVariables> </systemPropertyVariables>
<forkCount>1</forkCount> <forkCount>1</forkCount>
@@ -163,8 +165,7 @@
<systemPropertyVariables> <systemPropertyVariables>
<native.image.path> <native.image.path>
${project.build.directory}/${project.build.finalName}-runner</native.image.path> ${project.build.directory}/${project.build.finalName}-runner</native.image.path>
<java.util.logging.manager <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home> <maven.home>${maven.home}</maven.home>
</systemPropertyVariables> </systemPropertyVariables>
</configuration> </configuration>
@@ -187,4 +188,4 @@
</properties> </properties>
</profile> </profile>
</profiles> </profiles>
</project> </project>
@@ -0,0 +1,32 @@
package com.drinkool.provider;
import io.quarkus.security.identity.IdentityProviderManager;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.vertx.http.runtime.security.ChallengeData;
import io.quarkus.vertx.http.runtime.security.HttpAuthenticationMechanism;
import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class ManualSecurityFilter implements HttpAuthenticationMechanism {
@Override
public Uni<SecurityIdentity> authenticate(
RoutingContext context,
IdentityProviderManager identityProviderManager
) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException(
"Unimplemented method 'authenticate'"
);
}
@Override
public Uni<ChallengeData> getChallenge(RoutingContext context) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException(
"Unimplemented method 'getChallenge'"
);
}
}
+13 -13
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8"?>
<project <project
xmlns="http://maven.apache.org/POM/4.0.0" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
> >
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -20,11 +20,9 @@
<compiler-plugin.version>3.15.0</compiler-plugin.version> <compiler-plugin.version>3.15.0</compiler-plugin.version>
<maven.compiler.release>25</maven.compiler.release> <maven.compiler.release>25</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
>UTF-8</project.reporting.outputEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id> <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>3.32.4</quarkus.platform.version> <quarkus.platform.version>3.32.4</quarkus.platform.version>
<skipITs>true</skipITs> <skipITs>true</skipITs>
<surefire-plugin.version>3.5.4</surefire-plugin.version> <surefire-plugin.version>3.5.4</surefire-plugin.version>
@@ -48,6 +46,10 @@
<artifactId>jose4j</artifactId> <artifactId>jose4j</artifactId>
<version>0.9.6</version> <version>0.9.6</version>
</dependency> </dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security</artifactId>
</dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-graphql-client</artifactId> <artifactId>quarkus-smallrye-graphql-client</artifactId>
@@ -110,8 +112,7 @@
<configuration> <configuration>
<argLine>@{argLine}</argLine> <argLine>@{argLine}</argLine>
<systemPropertyVariables> <systemPropertyVariables>
<java.util.logging.manager <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home> <maven.home>${maven.home}</maven.home>
</systemPropertyVariables> </systemPropertyVariables>
<forkCount>1</forkCount> <forkCount>1</forkCount>
@@ -135,8 +136,7 @@
<systemPropertyVariables> <systemPropertyVariables>
<native.image.path> <native.image.path>
${project.build.directory}/${project.build.finalName}-runner</native.image.path> ${project.build.directory}/${project.build.finalName}-runner</native.image.path>
<java.util.logging.manager <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home> <maven.home>${maven.home}</maven.home>
</systemPropertyVariables> </systemPropertyVariables>
</configuration> </configuration>
@@ -158,4 +158,4 @@
</properties> </properties>
</profile> </profile>
</profiles> </profiles>
</project> </project>
@@ -1,39 +1,59 @@
package com.drinkool.controller; package com.drinkool.controller;
import com.drinkool.InternalValue;
import com.drinkool.dtos.GraphqlDto; import com.drinkool.dtos.GraphqlDto;
import io.smallrye.graphql.client.GraphQLClient;
import io.smallrye.graphql.client.GraphQLError;
import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient;
import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import java.util.List; import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
@Path("/api/eatery") @Path("/api/eatery")
public class EateryController { public class EateryController {
@GraphQLClient("eatery") @ConfigProperty(name = "quarkus.smallrye-graphql-client.eatery.url")
DynamicGraphQLClient dynamicClient; String eateryUrl;
@POST @POST
@Path("/graphql") @Path("/graphql")
public Response forward(GraphqlDto gqlRequest) public Response forward(
throws ExecutionException, InterruptedException { GraphqlDto gqlRequest,
io.smallrye.graphql.client.Response response = dynamicClient.executeSync( @Context HttpHeaders httpHeaders
gqlRequest.query, ) {
gqlRequest.variables DynamicGraphQLClientBuilder builder =
); DynamicGraphQLClientBuilder.newBuilder().url(eateryUrl);
if (response.hasError()) { httpHeaders
return Response.status(400) .getRequestHeaders()
.entity(response.getErrors().toString()) .forEach((name, values) -> {
String headerName = name.toLowerCase();
if (headerName.startsWith(InternalValue.headerId.toLowerCase())) {
if (!values.isEmpty()) {
builder.header(name, values.get(0));
}
}
});
try (DynamicGraphQLClient tempClient = builder.build()) {
io.smallrye.graphql.client.Response response = tempClient.executeSync(
gqlRequest.query,
gqlRequest.variables
);
if (response.hasError()) {
return Response.status(400).entity(response.getErrors()).build();
}
return Response.ok(response.getData()).build();
} catch (Exception e) {
e.printStackTrace();
return Response.serverError()
.entity("Lỗi kết nối tới service Eatery")
.build(); .build();
} }
return jakarta.ws.rs.core.Response.ok(
response.getData().toString()
).build();
} }
} }
@@ -0,0 +1,99 @@
package com.drinkool.filters;
import com.drinkool.InternalValue;
import com.drinkool.lib.utils.BaseHeaderAuthentication;
import io.quarkus.security.identity.IdentityProviderManager;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
import io.smallrye.mutiny.Uni;
import io.vertx.core.MultiMap;
import io.vertx.ext.web.RoutingContext;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.keys.HmacKey;
@ApplicationScoped
public class HeaderRolesFilter extends BaseHeaderAuthentication {
@ConfigProperty(name = "gateway.jwt.secret")
String SECRET_KEY;
private boolean isSystemClaim(String key) {
return List.of("iss", "sub", "aud", "exp", "nbf", "iat", "jti").contains(
key
);
}
private void removeForeignHeader(RoutingContext context) {
MultiMap headers = context.request().headers();
List<String> keysToRemove = new ArrayList<>();
for (String key : headers.names()) {
if (key.toLowerCase().startsWith(InternalValue.headerId.toLowerCase())) {
keysToRemove.add(key);
}
}
for (String key : keysToRemove) {
headers.remove(key);
}
}
@Override
public Uni<SecurityIdentity> authenticate(
RoutingContext context,
IdentityProviderManager identityProviderManager
) {
this.removeForeignHeader(context);
var cookie = context.request().getCookie(InternalValue.cookieName);
if (cookie == null) return Uni.createFrom().nullItem();
try {
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setRequireExpirationTime()
.setVerificationKey(new HmacKey(SECRET_KEY.getBytes()))
.build();
JwtClaims claims = jwtConsumer.processToClaims(cookie.getValue());
Map<String, Object> allClaims = claims.getClaimsMap();
allClaims.forEach((key, value) -> {
if (!isSystemClaim(key) && value != null) {
context
.request()
.headers()
.add(InternalValue.headerId + key, value.toString());
}
});
String role = context.request().getHeader(InternalValue.role);
String userId = context.request().getHeader(InternalValue.userId);
System.out.println(
"HeaderRolesFilter - Authenticated: " +
role +
" - " +
context.request().headers().toString()
);
return Uni.createFrom().item(
QuarkusSecurityIdentity.builder()
.setPrincipal(() -> userId)
.addRole(role)
.build()
);
} catch (Exception e) {
System.out.println(e.getMessage());
return Uni.createFrom().nullItem();
}
}
}
@@ -1,19 +1,15 @@
package com.drinkool.filters; package com.drinkool.filters;
import com.drinkool.InternalValue; import com.drinkool.InternalValue;
import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.Priorities; import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.*; import jakarta.ws.rs.container.*;
import jakarta.ws.rs.core.*; import jakarta.ws.rs.core.*;
import java.util.*; import java.util.*;
import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.resteasy.reactive.server.ServerRequestFilter;
import org.jboss.resteasy.reactive.server.ServerResponseFilter; import org.jboss.resteasy.reactive.server.ServerResponseFilter;
import org.jose4j.jws.AlgorithmIdentifiers; import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature; import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims; import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.keys.HmacKey; import org.jose4j.keys.HmacKey;
public class InternalHeaderGatewayFilter { public class InternalHeaderGatewayFilter {
@@ -21,60 +17,6 @@ public class InternalHeaderGatewayFilter {
@ConfigProperty(name = "gateway.jwt.secret") @ConfigProperty(name = "gateway.jwt.secret")
String SECRET_KEY; String SECRET_KEY;
private boolean isSystemClaim(String key) {
return List.of("iss", "sub", "aud", "exp", "nbf", "iat", "jti").contains(
key
);
}
@ServerRequestFilter(preMatching = true)
public Uni<Response> handleRequestHeaders(
ContainerRequestContext requestContext
) {
requestContext
.getHeaders()
.keySet()
.removeIf(
key ->
key.equalsIgnoreCase(InternalValue.headerId) ||
key.toLowerCase().startsWith(InternalValue.headerId.toLowerCase())
);
Map<String, Cookie> cookies = requestContext.getCookies();
Cookie authCookie = cookies.get(InternalValue.cookieName);
if (authCookie == null) return Uni.createFrom().nullItem();
return Uni.createFrom().item(() -> {
try {
String token = authCookie.getValue();
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setRequireExpirationTime()
.setVerificationKey(new HmacKey(SECRET_KEY.getBytes()))
.build();
JwtClaims claims = jwtConsumer.processToClaims(token);
Map<String, Object> allClaims = claims.getClaimsMap();
allClaims.forEach((key, value) -> {
if (!isSystemClaim(key) && value != null) {
String headerName = InternalValue.headerId + (key);
requestContext.getHeaders().add(headerName, value.toString());
}
});
} catch (Exception e) {
return Response.status(Response.Status.UNAUTHORIZED)
.entity("InvalidToken")
.build();
}
return null;
});
}
@ServerResponseFilter(priority = Priorities.USER + 100) @ServerResponseFilter(priority = Priorities.USER + 100)
public void handleResponseHeaders(ContainerResponseContext responseContext) { public void handleResponseHeaders(ContainerResponseContext responseContext) {
JwtClaims claims = new JwtClaims(); JwtClaims claims = new JwtClaims();
@@ -10,4 +10,10 @@ quarkus.container-image.additional-tags=latest
# Build # Build
quarkus.native.container-build=true quarkus.native.container-build=true
quarkus.native.remote-container-build=true quarkus.native.remote-container-build=true
quarkus.native.additional-build-args=--future-defaults=all quarkus.native.additional-build-args=--future-defaults=all
# Rest Client
quarkus.rest-client.account.url=http://account-service
# GraphQL Client
quarkus.smallrye-graphql-client.eatery.url=http://eatery-service/graphql
-4
View File
@@ -19,10 +19,6 @@ spec:
ports: ports:
- containerPort: 8080 - containerPort: 8080
env: env:
- name: QUARKUS_REST_CLIENT_ACCOUNT_URL
value: "http://account-service"
- name: QUARKUS_SMALLRYE_GRAPHQL_CLIENT_EATERY_URL
value: "http://eatery-service/graphql"
- name: GATEWAY_JWT_SECRET - name: GATEWAY_JWT_SECRET
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
+9 -6
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8"?>
<project <project
xmlns="http://maven.apache.org/POM/4.0.0" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
> >
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -24,7 +24,10 @@
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-security</artifactId> <artifactId>quarkus-security</artifactId>
<scope>provided</scope> </dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-http</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
@@ -60,4 +63,4 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>
@@ -0,0 +1,43 @@
package com.drinkool.lib.utils;
import com.drinkool.InternalValue;
import io.quarkus.security.identity.IdentityProviderManager;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.identity.request.TrustedAuthenticationRequest;
import io.quarkus.vertx.http.runtime.security.ChallengeData;
import io.quarkus.vertx.http.runtime.security.HttpAuthenticationMechanism;
import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
public abstract class BaseHeaderAuthentication
implements HttpAuthenticationMechanism
{
@Override
public Uni<SecurityIdentity> authenticate(
RoutingContext context,
IdentityProviderManager identityProviderManager
) {
String role = context.request().getHeader(InternalValue.role);
System.out.println(
"HeaderRolesFilter: " +
role +
" - " +
context.request().headers().toString()
);
if (role != null && !role.isEmpty()) {
return identityProviderManager.authenticate(
new TrustedAuthenticationRequest(role)
);
}
return Uni.createFrom().nullItem();
}
@Override
public Uni<ChallengeData> getChallenge(RoutingContext context) {
return Uni.createFrom().nullItem();
}
}
@@ -1,38 +0,0 @@
package com.drinkool.lib.utils;
import com.drinkool.InternalValue;
import io.quarkus.security.identity.AuthenticationRequestContext;
import io.quarkus.security.identity.IdentityProvider;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.identity.request.TrustedAuthenticationRequest;
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
import io.smallrye.mutiny.Uni;
import io.vertx.core.http.HttpServerRequest;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
@ApplicationScoped
public class HeaderIdentityProvider
implements IdentityProvider<TrustedAuthenticationRequest>
{
@Inject
HttpServerRequest httpServerRequest;
@Override
public Class<TrustedAuthenticationRequest> getRequestType() {
return TrustedAuthenticationRequest.class;
}
@Override
public Uni<SecurityIdentity> authenticate(
TrustedAuthenticationRequest request,
AuthenticationRequestContext context
) {
String role = httpServerRequest.getHeader(InternalValue.role);
return Uni.createFrom().item(
QuarkusSecurityIdentity.builder().addRole(role).build()
);
}
}