11package fr .github .vera .filters ;
22
3+ import fr .github .vera .config .ConfigProperties ;
34import jakarta .ws .rs .container .*;
45import jakarta .ws .rs .core .Response ;
56import jakarta .ws .rs .ext .Provider ;
67
78import java .io .IOException ;
9+ import java .lang .reflect .Method ;
810
911@ Provider
1012@ PreMatching
1113public class CorsFilter implements ContainerRequestFilter , ContainerResponseFilter {
14+ private boolean isPublicEndpoint (ContainerRequestContext requestContext ) {
15+ try {
16+ // Récupérer la méthode de la ressource depuis le contexte
17+ Object resourceMethodInvoker = requestContext
18+ .getProperty ("org.jboss.resteasy.core.ResourceMethodInvoker" );
19+
20+ if (resourceMethodInvoker != null ) {
21+ // Utiliser la réflexion pour accéder à la méthode
22+ Method getMethod = resourceMethodInvoker .getClass ().getMethod ("getMethod" );
23+ Method resourceMethod = (Method ) getMethod .invoke (resourceMethodInvoker );
24+
25+ // Vérifier si la méthode ou sa classe a l'annotation @Public
26+ return resourceMethod .isAnnotationPresent (Public .class ) ||
27+ resourceMethod .getDeclaringClass ().isAnnotationPresent (Public .class );
28+ }
29+ } catch (Exception e ) {
30+ return false ;
31+ }
32+ return false ;
33+ }
34+
1235
1336 @ Override
1437 public void filter (ContainerRequestContext requestContext ,
1538 ContainerResponseContext responseContext ) {
16- // Accepter toutes les origines
17- responseContext .getHeaders ().add ("Access-Control-Allow-Origin" , "*" );
18- responseContext .getHeaders ().add ("Access-Control-Allow-Headers" ,
19- "origin, content-type, accept, authorization, x-requested-with" );
20- // NE PAS mettre credentials à true quand origin est "*"
21- responseContext .getHeaders ().add ("Access-Control-Allow-Methods" ,
22- "GET, POST, PUT, DELETE, OPTIONS, HEAD" );
23- responseContext .getHeaders ().add ("Access-Control-Max-Age" , "3600" );
39+
40+ String origin = requestContext .getHeaderString ("Origin" );
41+ boolean isPublic = isPublicEndpoint (requestContext );
42+
43+ setCorsHeaders (responseContext , origin , isPublic );
2444 }
2545
2646 @ Override
2747 public void filter (ContainerRequestContext requestContext ) throws IOException {
28- // Gérer les requêtes OPTIONS (preflight)
48+
2949 if ("OPTIONS" .equals (requestContext .getMethod ())) {
30- Response response = Response .ok ()
31- .header ("Access-Control-Allow-Origin" , "*" )
32- .header ("Access-Control-Allow-Headers" ,
33- "origin, content-type, accept, authorization, x-requested-with" )
34- .header ("Access-Control-Allow-Methods" ,
35- "GET, POST, PUT, DELETE, OPTIONS, HEAD" )
36- .header ("Access-Control-Max-Age" , "3600" )
37- .build ();
38- requestContext .abortWith (response );
50+ // Pour les requêtes preflight, on doit déterminer si le chemin est public
51+ boolean isPublic = isPublicEndpoint (requestContext );
52+ String origin = requestContext .getHeaderString ("Origin" );
53+
54+ Response .ResponseBuilder responseBuilder = Response .ok ();
55+ setCorsHeaders (responseBuilder , origin , isPublic );
56+ requestContext .abortWith (responseBuilder .build ());
57+ }
58+ }
59+
60+ private void setCorsHeaders (ContainerResponseContext responseContext ,
61+ String origin , boolean isPublic ) {
62+
63+ if (isPublic ) {
64+ // Endpoint public : toutes origines autorisées
65+ responseContext .getHeaders ().add ("Access-Control-Allow-Origin" , "*" );
66+ } else {
67+ // Endpoint protégé : seulement les domaines autorisés
68+ if (origin != null && isOriginAllowed (origin )) {
69+ responseContext .getHeaders ().add ("Access-Control-Allow-Origin" , origin );
70+ responseContext .getHeaders ().add ("Access-Control-Allow-Credentials" , "true" );
71+ }
72+ }
73+
74+ // Headers communs
75+ responseContext .getHeaders ().add ("Access-Control-Allow-Headers" ,
76+ "origin, content-type, accept, authorization, x-requested-with, x-csrf-token" );
77+ responseContext .getHeaders ().add ("Access-Control-Allow-Methods" ,
78+ "GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH" );
79+ responseContext .getHeaders ().add ("Access-Control-Max-Age" , "3600" );
80+ responseContext .getHeaders ().add ("Access-Control-Expose-Headers" ,
81+ "x-csrf-token, authorization" );
82+ }
83+
84+ private void setCorsHeaders (Response .ResponseBuilder responseBuilder ,
85+ String origin , boolean isPublic ) {
86+
87+ if (isPublic ) {
88+ responseBuilder .header ("Access-Control-Allow-Origin" , "*" );
89+ } else if (origin != null && isOriginAllowed (origin )) {
90+ responseBuilder .header ("Access-Control-Allow-Origin" , origin );
91+ responseBuilder .header ("Access-Control-Allow-Credentials" , "true" );
92+ }
93+
94+ // Headers communs
95+ responseBuilder .header ("Access-Control-Allow-Headers" ,
96+ "origin, content-type, accept, authorization, x-requested-with, x-csrf-token" );
97+ responseBuilder .header ("Access-Control-Allow-Methods" ,
98+ "GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH" );
99+ responseBuilder .header ("Access-Control-Max-Age" , "3600" );
100+ }
101+
102+ private boolean isOriginAllowed (String origin ) {
103+ // Support multiple domains
104+ String allowedDomain = ConfigProperties .getInstance ().getProperty ("cors.allowed-domain" );
105+ String [] domains = allowedDomain .split ("," );
106+ for (String domain : domains ) {
107+ String trimmed = domain .trim ();
108+ if (origin .equals (trimmed )) {
109+ return true ;
110+ }
111+ // Support pour localhost avec différents ports
112+ if (trimmed .startsWith ("http://localhost" ) && origin .startsWith ("http://localhost" )) {
113+ return true ;
114+ }
39115 }
116+ return false ;
40117 }
41118}
0 commit comments