gdorks-web-generator-7cmse / chs-backend.html
secutorpro's picture
🐳 14/07 - 23:00 - tu as fais de bon travaille mon frere merci
b2fda5e verified
Raw
History Blame Contribute Delete
45.9 kB
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex, nofollow, noarchive, nosnippet, noimageindex, notranslate, none">
<meta name="googlebot" content="noindex, nofollow, noarchive, nosnippet, noimageindex, none">
<meta name="bingbot" content="noindex, nofollow, noarchive, nosnippet, none">
<meta name="duckduckbot" content="noindex, nofollow, none">
<meta name="yandexbot" content="noindex, nofollow, none">
<meta name="baiduspider" content="noindex, nofollow, none">
<meta name="slurp" content="noindex, nofollow, noarchive, none">
<meta name="referrer" content="no-referrer">
<meta http-equiv="x-dns-prefetch-control" content="off">
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="expires" content="0">
<link rel="canonical" href="#">
<title>CHS Backend Java — SentinelAI</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="chs-backend.css">
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
sans: ['Inter', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
}
}
}
}
</script>
</head>
<body class="bg-slate-950 text-slate-200 font-sans antialiased min-h-screen overflow-x-hidden">
<!-- Animated Background -->
<div class="fixed inset-0 z-0 pointer-events-none">
<div class="grid-bg"></div>
<div class="absolute top-0 left-1/4 w-[600px] h-[600px] bg-indigo-600/5 rounded-full blur-3xl animate-pulse-slow"></div>
<div class="absolute bottom-0 right-1/4 w-[600px] h-[600px] bg-blue-600/5 rounded-full blur-3xl animate-pulse-slow-delayed"></div>
</div>
<!-- Navbar -->
<nav class="relative z-20 border-b border-slate-800/60 backdrop-blur-xl bg-slate-950/90 sticky top-0">
<div class="max-w-[1600px] mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-14">
<div class="flex items-center gap-2.5">
<div class="w-8 h-8 bg-gradient-to-br from-indigo-400 to-violet-600 rounded-lg flex items-center justify-center shadow-lg shadow-indigo-500/20">
<i data-lucide="plug" class="w-4 h-4 text-white"></i>
</div>
<div>
<span class="text-base font-bold text-white tracking-tight">Sentinel<span class="text-indigo-400">AI</span></span>
<span class="hidden sm:inline text-xs text-slate-500 ml-2 font-mono">CHS BACKEND JAVA</span>
</div>
</div>
<div class="hidden md:flex items-center gap-1">
<a href="command-center.html" class="nav-link px-3 py-1.5 rounded-lg text-xs font-medium transition-all"><i data-lucide="layout-dashboard" class="w-3.5 h-3.5 inline mr-1"></i>Dashboard</a>
<a href="index.html" class="nav-link px-3 py-1.5 rounded-lg text-xs font-medium transition-all"><i data-lucide="search" class="w-3.5 h-3.5 inline mr-1"></i>GDorks</a>
<a href="threats.html" class="nav-link px-3 py-1.5 rounded-lg text-xs font-medium transition-all"><i data-lucide="alert-triangle" class="w-3.5 h-3.5 inline mr-1"></i>Threats</a>
<a href="network.html" class="nav-link px-3 py-1.5 rounded-lg text-xs font-medium transition-all"><i data-lucide="network" class="w-3.5 h-3.5 inline mr-1"></i>Network</a>
<a href="seo-mesh-normal.html" class="nav-link px-3 py-1.5 rounded-lg text-xs font-medium transition-all"><i data-lucide="network" class="w-3.5 h-3.5 inline mr-1"></i>Mesh Normal</a>
<a href="seo-mesh-inverse.html" class="nav-link px-3 py-1.5 rounded-lg text-xs font-medium transition-all"><i data-lucide="brain-circuit" class="w-3.5 h-3.5 inline mr-1"></i>Mesh Inversé</a>
<a href="cognitive-inverse-mesh.html" class="nav-link px-3 py-1.5 rounded-lg text-xs font-medium transition-all"><i data-lucide="brain-circuit" class="w-3.5 h-3.5 inline mr-1"></i>Cognitive Inversé</a>
<a href="cognitive-seo-geo-mesh.html" class="nav-link px-3 py-1.5 rounded-lg text-xs font-medium transition-all"><i data-lucide="brain" class="w-3.5 h-3.5 inline mr-1"></i>Cognitive SEO/GEO</a>
<a href="seo-inverse.html" class="nav-link px-3 py-1.5 rounded-lg text-xs font-medium transition-all"><i data-lucide="eye-off" class="w-3.5 h-3.5 inline mr-1"></i>SEO Inverse</a>
<a href="chs-backend.html" class="nav-link active px-3 py-1.5 rounded-lg text-xs font-medium transition-all"><i data-lucide="plug" class="w-3.5 h-3.5 inline mr-1"></i>CHS Backend</a>
</div>
<div class="flex items-center gap-3">
<div class="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-indigo-500/10 border border-indigo-500/20">
<div class="w-2 h-2 bg-indigo-400 rounded-full animate-pulse"></div>
<span class="text-xs font-semibold text-indigo-400 font-mono">JAVA BACKEND</span>
</div>
<button onclick="toggleMobileMenu()" class="md:hidden p-2 text-slate-400 hover:text-white"><i data-lucide="menu" class="w-5 h-5"></i></button>
</div>
</div>
</div>
<div id="mobileMenu" class="hidden md:hidden border-t border-slate-800/60 bg-slate-950/95 backdrop-blur-xl">
<div class="px-4 py-3 space-y-1">
<a href="command-center.html" class="block px-3 py-2 rounded-lg text-sm font-medium text-slate-400 hover:text-white hover:bg-slate-800">Dashboard</a>
<a href="index.html" class="block px-3 py-2 rounded-lg text-sm font-medium text-slate-400 hover:text-white hover:bg-slate-800">GDorks</a>
<a href="threats.html" class="block px-3 py-2 rounded-lg text-sm font-medium text-slate-400 hover:text-white hover:bg-slate-800">Threats</a>
<a href="network.html" class="block px-3 py-2 rounded-lg text-sm font-medium text-slate-400 hover:text-white hover:bg-slate-800">Network</a>
<a href="seo-mesh-normal.html" class="block px-3 py-2 rounded-lg text-sm font-medium text-slate-400 hover:text-white hover:bg-slate-800">Mesh Normal</a>
<a href="seo-mesh-inverse.html" class="block px-3 py-2 rounded-lg text-sm font-medium text-slate-400 hover:text-white hover:bg-slate-800">Mesh Inversé</a>
<a href="cognitive-inverse-mesh.html" class="block px-3 py-2 rounded-lg text-sm font-medium text-slate-400 hover:text-white hover:bg-slate-800">Cognitive Inversé</a>
<a href="cognitive-seo-geo-mesh.html" class="block px-3 py-2 rounded-lg text-sm font-medium text-slate-400 hover:text-white hover:bg-slate-800">Cognitive SEO/GEO</a>
<a href="seo-inverse.html" class="block px-3 py-2 rounded-lg text-sm font-medium text-slate-400 hover:text-white hover:bg-slate-800">SEO Inverse</a>
<a href="chs-backend.html" class="block px-3 py-2 rounded-lg text-sm font-medium text-indigo-400 bg-indigo-500/10">CHS Backend</a>
</div>
</div>
</nav>
<!-- Main Content -->
<div class="relative z-10 max-w-[1600px] mx-auto px-4 sm:px-6 lg:px-8 py-6">
<!-- Status Banner -->
<div class="mb-6 flex items-center gap-3 px-4 py-2.5 bg-slate-900/50 border border-slate-800/60 rounded-xl backdrop-blur-sm flex-wrap">
<div class="flex items-center gap-2">
<div class="w-2 h-2 bg-indigo-400 rounded-full animate-pulse"></div>
<span class="text-xs font-mono text-indigo-400">CHS BACKEND JAVA ACTIF</span>
</div>
<div class="h-4 w-px bg-slate-800"></div>
<span class="text-xs font-mono text-slate-500" id="systemTime">--:--:--</span>
<div class="h-4 w-px bg-slate-800"></div>
<span class="text-xs font-mono text-slate-500">STACK: <span class="text-slate-300">Java 17 + Google API Client Services</span></span>
<div class="ml-auto flex items-center gap-2">
<span class="text-xs font-mono text-slate-500">MODULES: <span class="text-indigo-400">3</span></span>
<div class="h-4 w-px bg-slate-800"></div>
<span class="text-xs font-mono text-slate-500">APIs: <span class="text-cyan-400">Search Console · Indexing · Custom Search</span></span>
</div>
</div>
<!-- Hero -->
<div class="mb-8 text-center">
<h1 class="text-3xl md:text-4xl font-bold text-white mb-3 tracking-tight">
CHS Backend <span class="text-transparent bg-clip-text bg-gradient-to-r from-indigo-400 to-violet-400">Java Integration</span>
</h1>
<p class="text-slate-400 text-base max-w-2xl mx-auto leading-relaxed">
Remplacement des appels décoratifs par les vrais clients Java Google — 3 APIs, 3 modules, 1 pom.xml
</p>
</div>
<!-- Stats Row -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
<div class="stat-card bg-slate-900/50 border border-slate-800/80 rounded-xl p-4 backdrop-blur-sm">
<div class="flex items-center justify-between mb-2">
<span class="text-xs font-medium text-slate-500 uppercase tracking-wider">Modules</span>
<i data-lucide="boxes" class="w-4 h-4 text-indigo-400"></i>
</div>
<div class="text-2xl font-bold text-indigo-400 font-mono">3</div>
<div class="text-xs text-slate-500 font-mono mt-1">Scanner · Indexing · SERP</div>
</div>
<div class="stat-card bg-slate-900/50 border border-slate-800/80 rounded-xl p-4 backdrop-blur-sm">
<div class="flex items-center justify-between mb-2">
<span class="text-xs font-medium text-slate-500 uppercase tracking-wider">Google APIs</span>
<i data-lucide="cloud" class="w-4 h-4 text-cyan-400"></i>
</div>
<div class="text-2xl font-bold text-cyan-400 font-mono">3</div>
<div class="text-xs text-slate-500 font-mono mt-1">Search Console · Indexing · CSE</div>
</div>
<div class="stat-card bg-slate-900/50 border border-slate-800/80 rounded-xl p-4 backdrop-blur-sm">
<div class="flex items-center justify-between mb-2">
<span class="text-xs font-medium text-slate-500 uppercase tracking-wider">Auth OAuth2</span>
<i data-lucide="key-round" class="w-4 h-4 text-green-400"></i>
</div>
<div class="text-2xl font-bold text-green-400 font-mono">1</div>
<div class="text-xs text-slate-500 font-mono mt-1">Service Account unifié</div>
</div>
<div class="stat-card bg-slate-900/50 border border-slate-800/80 rounded-xl p-4 backdrop-blur-sm">
<div class="flex items-center justify-between mb-2">
<span class="text-xs font-medium text-slate-500 uppercase tracking-wider">Dépendances</span>
<i data-lucide="package" class="w-4 h-4 text-amber-400"></i>
</div>
<div class="text-2xl font-bold text-amber-400 font-mono">5</div>
<div class="text-xs text-slate-500 font-mono mt-1">Maven dependencies</div>
</div>
</div>
<!-- Tab Navigation -->
<div class="mb-6 flex gap-2 overflow-x-auto pb-1">
<button onclick="switchTab('pom', this)" class="tab-btn active px-4 py-2 rounded-lg text-xs font-semibold whitespace-nowrap transition-all">
<i data-lucide="file-code" class="w-3.5 h-3.5 inline mr-1"></i>pom.xml
</button>
<button onclick="switchTab('auth', this)" class="tab-btn px-4 py-2 rounded-lg text-xs font-semibold whitespace-nowrap transition-all">
<i data-lucide="key-round" class="w-3.5 h-3.5 inline mr-1"></i>Auth Provider
</button>
<button onclick="switchTab('modules', this)" class="tab-btn px-4 py-2 rounded-lg text-xs font-semibold whitespace-nowrap transition-all">
<i data-lucide="boxes" class="w-3.5 h-3.5 inline mr-1"></i>Modules 1·4·6
</button>
<button onclick="switchTab('bootstrap', this)" class="tab-btn px-4 py-2 rounded-lg text-xs font-semibold whitespace-nowrap transition-all">
<i data-lucide="play" class="w-3.5 h-3.5 inline mr-1"></i>Bootstrap
</button>
<button onclick="switchTab('recap', this)" class="tab-btn px-4 py-2 rounded-lg text-xs font-semibold whitespace-nowrap transition-all">
<i data-lucide="table" class="w-3.5 h-3.5 inline mr-1"></i>Récapitulatif
</button>
</div>
<!-- Tab: pom.xml -->
<div id="tab-pom" class="tab-content mb-6">
<div class="module-card bg-slate-900/50 border border-slate-800/80 rounded-xl backdrop-blur-sm overflow-hidden">
<div class="flex items-center justify-between px-5 py-3 border-b border-slate-800/60">
<div class="flex items-center gap-2">
<i data-lucide="file-code" class="w-4 h-4 text-indigo-400"></i>
<h2 class="text-sm font-semibold text-white">Dépendances Maven — <code class="text-indigo-400">pom.xml</code></h2>
</div>
<button onclick="copyBlock('pomCode')" class="text-xs text-indigo-400 hover:text-indigo-300 transition-colors font-mono flex items-center gap-1">
<i data-lucide="copy" class="w-3.5 h-3.5"></i>COPIER
</button>
</div>
<div class="p-5">
<pre class="code-block p-4 text-slate-300 max-h-[500px] overflow-y-auto" id="pomCode">&lt;dependencies&gt;
&lt;!-- ============================================ --&gt;
&lt;!-- Google API Client Services (Java) --&gt;
&lt;!-- ============================================ --&gt;
&lt;!-- 🔍 Module 1 : Search Console (URL Inspection) --&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.apis&lt;/groupId&gt;
&lt;artifactId&gt;google-api-services-searchconsole&lt;/artifactId&gt;
&lt;version&gt;v1-rev20240501-2.0.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- 📨 Module 4 : Indexing API --&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.apis&lt;/groupId&gt;
&lt;artifactId&gt;google-api-services-indexing&lt;/artifactId&gt;
&lt;version&gt;v3-rev20240501-2.0.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- 📡 Module 6 : Custom Search JSON API --&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.apis&lt;/groupId&gt;
&lt;artifactId&gt;google-api-services-customsearch&lt;/artifactId&gt;
&lt;version&gt;v1-rev20240501-2.0.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- 🔐 Google Auth Library --&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.auth&lt;/groupId&gt;
&lt;artifactId&gt;google-auth-library-oauth2-http&lt;/artifactId&gt;
&lt;version&gt;1.23.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- 📦 Jackson (JSON parsing) --&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.http-client&lt;/groupId&gt;
&lt;artifactId&gt;google-http-client-jackson2&lt;/artifactId&gt;
&lt;version&gt;1.43.3&lt;/version&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;</pre>
</div>
</div>
</div>
<!-- Tab: Auth Provider -->
<div id="tab-auth" class="tab-content hidden mb-6">
<div class="module-card bg-slate-900/50 border border-slate-800/80 rounded-xl backdrop-blur-sm overflow-hidden">
<div class="flex items-center justify-between px-5 py-3 border-b border-slate-800/60">
<div class="flex items-center gap-2">
<i data-lucide="key-round" class="w-4 h-4 text-green-400"></i>
<h2 class="text-sm font-semibold text-white">Authentification unifiée — <code class="text-green-400">GoogleAuthProvider.java</code></h2>
</div>
<button onclick="copyBlock('authCode')" class="text-xs text-green-400 hover:text-green-300 transition-colors font-mono flex items-center gap-1">
<i data-lucide="copy" class="w-3.5 h-3.5"></i>COPIER
</button>
</div>
<div class="p-5">
<div class="mb-4 flex flex-wrap gap-2">
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[11px] font-semibold bg-green-500/10 text-green-400 border border-green-500/20">
<i data-lucide="shield-check" class="w-3 h-3"></i>OAuth2 Service Account
</span>
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[11px] font-semibold bg-indigo-500/10 text-indigo-400 border border-indigo-500/20">
<i data-lucide="repeat" class="w-3 h-3"></i>Réutilisable
</span>
</div>
<pre class="code-block p-4 text-slate-300 max-h-[500px] overflow-y-auto" id="authCode">package com.chs.auth;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.List;
public class GoogleAuthProvider {
private static final JacksonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static GoogleCredentials credentials;
/**
* Charge les credentials OAuth2 depuis un compte de service.
*/
public static GoogleCredentials loadCredentials(String keyPath, List&lt;String&gt; scopes)
throws IOException {
credentials = ServiceAccountCredentials
.fromStream(new FileInputStream(keyPath))
.createScoped(scopes);
return credentials;
}
/**
* Retourne un HttpCredentialsAdapter réutilisable.
*/
public static HttpCredentialsAdapter getAdapter() {
if (credentials == null) {
throw new IllegalStateException("loadCredentials() doit être appelé d'abord");
}
return new HttpCredentialsAdapter(credentials);
}
public static JacksonFactory getJsonFactory() { return JSON_FACTORY; }
public static GoogleNetHttpTransport getTransport()
throws GeneralSecurityException, IOException {
return GoogleNetHttpTransport.newTrustedTransport();
}
}</pre>
</div>
</div>
</div>
<!-- Tab: Modules 1·4·6 -->
<div id="tab-modules" class="tab-content hidden mb-6">
<div class="space-y-6">
<!-- Module 1 -->
<div class="module-card bg-slate-900/50 border border-blue-500/20 rounded-xl backdrop-blur-sm overflow-hidden">
<div class="flex items-center justify-between px-5 py-3 border-b border-slate-800/60">
<div class="flex items-center gap-2">
<i data-lucide="search" class="w-4 h-4 text-blue-400"></i>
<h2 class="text-sm font-semibold text-white">Module 1 — Scanner Google (URL Inspection API v1)</h2>
</div>
<button onclick="copyBlock('m1Code')" class="text-xs text-blue-400 hover:text-blue-300 transition-colors font-mono flex items-center gap-1">
<i data-lucide="copy" class="w-3.5 h-3.5"></i>COPIER
</button>
</div>
<div class="p-5">
<div class="mb-4 overflow-x-auto">
<table class="api-table w-full border-collapse">
<tr>
<td style="width:160px" class="font-mono text-slate-500"><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-blue-500/10 text-blue-400 border border-blue-500/20">API</span></td>
<td class="text-slate-300">Search Console v1 — <code class="text-blue-400">urlInspection.index.inspect</code></td>
</tr>
<tr>
<td class="font-mono text-slate-500"><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-blue-500/10 text-blue-400 border border-blue-500/20">Scope OAuth</span></td>
<td class="font-mono text-xs text-cyan-400"><code>https://www.googleapis.com/auth/webmasters</code></td>
</tr>
<tr>
<td class="font-mono text-slate-500"><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-blue-500/10 text-blue-400 border border-blue-500/20">Endpoint</span></td>
<td class="font-mono text-xs text-cyan-400"><code>POST /v1/urlInspection/index:inspect</code></td>
</tr>
</table>
</div>
<pre class="code-block p-4 text-slate-300 max-h-[400px] overflow-y-auto" id="m1Code">package com.chs.module1;
import com.chs.auth.GoogleAuthProvider;
import com.google.api.services.searchconsole.v1.SearchConsole;
import com.google.api.services.searchconsole.v1.model.*;
import java.io.IOException;
import java.security.GeneralSecurityException;
public class CanonicalScanner {
private final SearchConsole client;
private final String siteUrl;
public CanonicalScanner(String siteUrl) throws GeneralSecurityException, IOException {
this.siteUrl = siteUrl;
this.client = new SearchConsole.Builder(
GoogleAuthProvider.getTransport(),
GoogleAuthProvider.getJsonFactory(),
GoogleAuthProvider.getAdapter())
.setApplicationName("canonical-hijack-shield")
.build();
}
/**
* Inspecte une URL via l'API Search Console.
* Retourne le verdict canonique (userCanonical vs googleCanonical).
*/
public ScanResult inspect(String targetUrl) throws IOException {
InspectUrlIndexRequest request = new InspectUrlIndexRequest()
.setInspectionUrl(targetUrl)
.setSiteUrl(this.siteUrl)
.setLanguageCode("fr");
InspectUrlIndexResponse response = client
.urlInspection()
.index()
.inspect(request)
.execute();
IndexStatusResult result = response.getInspectionResult().getIndexStatusResult();
// 🔴 Détection du verrou canonique parasite
String userCanonical = result.getUserCanonical();
String googleCanonical = result.getGoogleCanonical();
boolean isParasited = userCanonical != null
&amp;&amp; googleCanonical != null
&amp;&amp; !userCanonical.equals(googleCanonical);
return new ScanResult(
result.getVerdict(),
result.getCoverageState(),
userCanonical,
googleCanonical,
isParasited ? "parameter_injection" : null,
isParasited,
result.getLastCrawlTime()
);
}
}</pre>
</div>
</div>
<!-- Module 4 -->
<div class="module-card bg-slate-900/50 border border-green-500/20 rounded-xl backdrop-blur-sm overflow-hidden">
<div class="flex items-center justify-between px-5 py-3 border-b border-slate-800/60">
<div class="flex items-center gap-2">
<i data-lucide="send" class="w-4 h-4 text-green-400"></i>
<h2 class="text-sm font-semibold text-white">Module 4 — Indexing API v3 (ping Google après nettoyage)</h2>
</div>
<button onclick="copyBlock('m4Code')" class="text-xs text-green-400 hover:text-green-300 transition-colors font-mono flex items-center gap-1">
<i data-lucide="copy" class="w-3.5 h-3.5"></i>COPIER
</button>
</div>
<div class="p-5">
<div class="mb-4 overflow-x-auto">
<table class="api-table w-full border-collapse">
<tr>
<td style="width:160px" class="font-mono text-slate-500"><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-green-500/10 text-green-400 border border-green-500/20">API</span></td>
<td class="text-slate-300">Indexing API v3 — <code class="text-green-400">urlNotifications.publish</code></td>
</tr>
<tr>
<td class="font-mono text-slate-500"><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-green-500/10 text-green-400 border border-green-500/20">Scope OAuth</span></td>
<td class="font-mono text-xs text-cyan-400"><code>https://www.googleapis.com/auth/indexing</code></td>
</tr>
<tr>
<td class="font-mono text-slate-500"><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-green-500/10 text-green-400 border border-green-500/20">Endpoint</span></td>
<td class="font-mono text-xs text-cyan-400"><code>POST /v3/urlNotifications:publish</code></td>
</tr>
</table>
</div>
<pre class="code-block p-4 text-slate-300 max-h-[400px] overflow-y-auto" id="m4Code">package com.chs.module4;
import com.chs.auth.GoogleAuthProvider;
import com.google.api.services.indexing.v3.Indexing;
import com.google.api.services.indexing.v3.model.*;
import java.io.IOException;
import java.security.GeneralSecurityException;
public class IndexingNotifier {
private final Indexing client;
public IndexingNotifier() throws GeneralSecurityException, IOException {
this.client = new Indexing.Builder(
GoogleAuthProvider.getTransport(),
GoogleAuthProvider.getJsonFactory(),
GoogleAuthProvider.getAdapter())
.setApplicationName("canonical-hijack-shield")
.build();
}
/**
* Notifie Google que l'URL a été mise à jour (canonical corrigé).
* Équivaut à : POST /v3/urlNotifications:publish
* { "url": "...", "type": "URL_UPDATED" }
*/
public boolean notifyUrlUpdated(String url) throws IOException {
UrlNotification notification = new UrlNotification()
.setUrl(url)
.setType("URL_UPDATED");
UrlNotificationMetadata response = client
.urlNotifications()
.publish(notification)
.execute();
// ✅ 200 OK → Google a bien reçu la notification
return response != null
&amp;&amp; response.getLatestUpdate() != null
&amp;&amp; response.getLatestUpdate().getUrl().equals(url);
}
/**
* Notifie que l'URL a été supprimée (si nécessaire).
*/
public boolean notifyUrlRemoved(String url) throws IOException {
UrlNotification notification = new UrlNotification()
.setUrl(url)
.setType("URL_DELETED");
UrlNotificationMetadata response = client
.urlNotifications()
.publish(notification)
.execute();
return response != null;
}
}</pre>
</div>
</div>
<!-- Module 6 -->
<div class="module-card bg-slate-900/50 border border-red-500/20 rounded-xl backdrop-blur-sm overflow-hidden">
<div class="flex items-center justify-between px-5 py-3 border-b border-slate-800/60">
<div class="flex items-center gap-2">
<i data-lucide="radar" class="w-4 h-4 text-red-400"></i>
<h2 class="text-sm font-semibold text-white">Module 6 — Custom Search JSON API v1 (surveillance SERP)</h2>
</div>
<button onclick="copyBlock('m6Code')" class="text-xs text-red-400 hover:text-red-300 transition-colors font-mono flex items-center gap-1">
<i data-lucide="copy" class="w-3.5 h-3.5"></i>COPIER
</button>
</div>
<div class="p-5">
<div class="mb-4 overflow-x-auto">
<table class="api-table w-full border-collapse">
<tr>
<td style="width:160px" class="font-mono text-slate-500"><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-red-500/10 text-red-400 border border-red-500/20">API</span></td>
<td class="text-slate-300">Custom Search JSON API v1</td>
</tr>
<tr>
<td class="font-mono text-slate-500"><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-red-500/10 text-red-400 border border-red-500/20">Auth</span></td>
<td class="font-mono text-xs text-cyan-400">API Key (<code>GOOGLE_API_KEY</code>) + Search Engine ID (<code>CX</code>)</td>
</tr>
<tr>
<td class="font-mono text-slate-500"><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-red-500/10 text-red-400 border border-red-500/20">Endpoint</span></td>
<td class="font-mono text-xs text-cyan-400"><code>GET /customsearch/v1?key=...&amp;cx=...&amp;q=...</code></td>
</tr>
</table>
</div>
<pre class="code-block p-4 text-slate-300 max-h-[400px] overflow-y-auto" id="m6Code">package com.chs.module6;
import com.chs.auth.GoogleAuthProvider;
import com.google.api.services.customsearch.v1.CustomSearchAPI;
import com.google.api.services.customsearch.v1.model.*;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;
public class SerpMonitor {
private final CustomSearchAPI client;
private final String cx; // Search Engine ID (configuré dans cse.google.com)
public SerpMonitor(String apiKey, String cx) throws GeneralSecurityException, IOException {
this.cx = cx;
this.client = new CustomSearchAPI.Builder(
GoogleAuthProvider.getTransport(),
GoogleAuthProvider.getJsonFactory(),
request -> { /* pas d'auth OAuth ici, on utilise la clé API en paramètre */ })
.setApplicationName("canonical-hijack-shield")
.build();
}
/**
* Surveillance SERP : vérifie si des URLs parasites apparaissent
* pour une requête donnée sur un domaine spécifique.
*/
public MonitorResult monitor(String domain, String keyword, String apiKey) throws IOException {
String query = String.format("site:%s \"%s\"", domain, keyword);
CustomSearchAPI.Cse.List request = client.cse().list()
.setCx(this.cx)
.setKey(apiKey)
.setQ(query)
.setLr("lang_fr");
Search results = request.execute();
List&lt;SerpEntry&gt; cleanUrls = new ArrayList&lt;&gt;();
List&lt;SerpEntry&gt; parasiteUrls = new ArrayList&lt;&gt;();
if (results.getItems() != null) {
for (int i = 0; i &lt; results.getItems().size(); i++) {
Result item = results.getItems().get(i);
String link = item.getLink();
// 🔴 Détection d'URL parasite (paramètres suspects)
boolean isParasite = link.contains("?parasite=")
|| link.contains("?utm_source=")
|| link.contains("?gclid=")
|| link.contains("?fbclid=");
SerpEntry entry = new SerpEntry(i + 1, link, isParasite);
if (isParasite) {
parasiteUrls.add(entry);
} else {
cleanUrls.add(entry);
}
}
}
boolean alertTriggered = !parasiteUrls.isEmpty();
return new MonitorResult(
results.getSearchInformation() != null
? results.getSearchInformation().getTotalResults() : 0,
cleanUrls,
parasiteUrls,
alertTriggered ? "degraded" : "clean",
alertTriggered
);
}
}</pre>
</div>
</div>
</div>
</div>
<!-- Tab: Bootstrap -->
<div id="tab-bootstrap" class="tab-content hidden mb-6">
<div class="module-card bg-slate-900/50 border border-slate-800/80 rounded-xl backdrop-blur-sm overflow-hidden">
<div class="flex items-center justify-between px-5 py-3 border-b border-slate-800/60">
<div class="flex items-center gap-2">
<i data-lucide="play" class="w-4 h-4 text-indigo-400"></i>
<h2 class="text-sm font-semibold text-white">Bootstrap — <code class="text-indigo-400">ChsApplication.java</code></h2>
</div>
<button onclick="copyBlock('bootstrapCode')" class="text-xs text-indigo-400 hover:text-indigo-300 transition-colors font-mono flex items-center gap-1">
<i data-lucide="copy" class="w-3.5 h-3.5"></i>COPIER
</button>
</div>
<div class="p-5">
<pre class="code-block p-4 text-slate-300 max-h-[500px] overflow-y-auto" id="bootstrapCode">package com.chs;
import com.chs.auth.GoogleAuthProvider;
import com.chs.module1.CanonicalScanner;
import com.chs.module1.ScanResult;
import com.chs.module4.IndexingNotifier;
import com.chs.module6.MonitorResult;
import com.chs.module6.SerpMonitor;
import com.google.auth.oauth2.GoogleCredentials;
import java.util.List;
public class ChsApplication {
public static void main(String[] args) throws Exception {
// 🔐 1. Charger les credentials
String keyPath = System.getenv("CHS_GOOGLE_CREDENTIALS");
GoogleAuthProvider.loadCredentials(keyPath, List.of(
"https://www.googleapis.com/auth/webmasters", // M1
"https://www.googleapis.com/auth/indexing" // M4
));
// 🔍 2. Module 1 — Scanner
CanonicalScanner scanner = new CanonicalScanner(
"sc-domain:mediapart.fr");
ScanResult scan = scanner.inspect(
"https://www.mediapart.fr/journal/france/270917/la-nouvelle-recherche-de-financement");
System.out.println("📋 Verdict: " + scan.verdict());
System.out.println("🔴 Parasité: " + scan.isParasited());
System.out.println("📐 User Canonical: " + scan.userCanonical());
System.out.println("⚠️ Google Canonical: " + scan.googleCanonical());
// 🔧 3. Module 4 — Si parasité, on nettoie + ping
if (scan.isParasited()) {
IndexingNotifier notifier = new IndexingNotifier();
boolean ok = notifier.notifyUrlUpdated(scan.userCanonical());
System.out.println("📨 Indexing API ping → " + (ok ? "✅ OK" : "❌ Échec"));
}
// 📡 4. Module 6 — Surveillance
String apiKey = System.getenv("CHS_GOOGLE_API_KEY");
String cx = System.getenv("CHS_CSE_ID");
SerpMonitor monitor = new SerpMonitor(apiKey, cx);
MonitorResult mon = monitor.monitor("mediapart.fr", "fortune", apiKey);
System.out.println("📡 SERP Status: " + mon.status());
System.out.println("🧹 Clean URLs: " + mon.cleanUrls().size());
System.out.println("🦠 Parasite URLs: " + mon.parasiteUrls().size());
System.out.println("🚨 Alerte: " + mon.alertTriggered());
}
}</pre>
</div>
</div>
</div>
<!-- Tab: Récapitulatif -->
<div id="tab-recap" class="tab-content hidden mb-6">
<div class="module-card bg-slate-900/50 border border-slate-800/80 rounded-xl backdrop-blur-sm overflow-hidden">
<div class="flex items-center justify-between px-5 py-3 border-b border-slate-800/60">
<div class="flex items-center gap-2">
<i data-lucide="table" class="w-4 h-4 text-indigo-400"></i>
<h2 class="text-sm font-semibold text-white">Récapitulatif — Mapping Modules ↔ APIs Google</h2>
</div>
<button onclick="copyBlock('recapCode')" class="text-xs text-indigo-400 hover:text-indigo-300 transition-colors font-mono flex items-center gap-1">
<i data-lucide="copy" class="w-3.5 h-3.5"></i>COPIER
</button>
</div>
<div class="p-5 overflow-x-auto">
<table class="api-table w-full border-collapse">
<thead>
<tr>
<th>Module CHS</th>
<th>Google API</th>
<th>Dépendance Maven</th>
<th>Scope OAuth</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-blue-500/10 text-blue-400 border border-blue-500/20">M1 Scanner</span></td>
<td class="text-slate-300">Search Console v1</td>
<td class="font-mono text-xs text-cyan-400"><code>google-api-services-searchconsole</code></td>
<td class="font-mono text-xs text-cyan-400"><code>webmasters</code></td>
</tr>
<tr>
<td><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-green-500/10 text-green-400 border border-green-500/20">M4 Remediation</span></td>
<td class="text-slate-300">Indexing API v3</td>
<td class="font-mono text-xs text-cyan-400"><code>google-api-services-indexing</code></td>
<td class="font-mono text-xs text-cyan-400"><code>indexing</code></td>
</tr>
<tr>
<td><span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-red-500/10 text-red-400 border border-red-500/20">M6 Monitoring</span></td>
<td class="text-slate-300">Custom Search JSON v1</td>
<td class="font-mono text-xs text-cyan-400"><code>google-api-services-customsearch</code></td>
<td class="font-mono text-xs text-amber-400">API Key (pas OAuth)</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Architecture Flow -->
<div class="mt-6 bg-slate-900/50 border border-indigo-500/20 rounded-xl backdrop-blur-sm overflow-hidden">
<div class="flex items-center justify-between px-5 py-3 border-b border-slate-800/60">
<div class="flex items-center gap-2">
<i data-lucide="git-branch" class="w-4 h-4 text-indigo-400"></i>
<h2 class="text-sm font-semibold text-white">Flux d'Architecture CHS</h2>
</div>
</div>
<div class="p-5">
<div class="flex flex-col md:flex-row items-center justify-center gap-3 text-center">
<div class="bg-blue-500/10 border border-blue-500/20 rounded-xl px-5 py-4 min-w-[160px]">
<i data-lucide="search" class="w-6 h-6 text-blue-400 mx-auto mb-2"></i>
<div class="text-sm font-bold text-blue-400">M1 Scanner</div>
<div class="text-[10px] text-slate-500 font-mono">URL Inspection</div>
</div>
<i data-lucide="arrow-right" class="w-5 h-5 text-slate-600 hidden md:block"></i>
<i data-lucide="arrow-down" class="w-5 h-5 text-slate-600 md:hidden"></i>
<div class="bg-amber-500/10 border border-amber-500/20 rounded-xl px-5 py-4 min-w-[160px]">
<i data-lucide="alert-triangle" class="w-6 h-6 text-amber-400 mx-auto mb-2"></i>
<div class="text-sm font-bold text-amber-400">Verdict</div>
<div class="text-[10px] text-slate-500 font-mono">Parasité ?</div>
</div>
<i data-lucide="arrow-right" class="w-5 h-5 text-slate-600 hidden md:block"></i>
<i data-lucide="arrow-down" class="w-5 h-5 text-slate-600 md:hidden"></i>
<div class="bg-green-500/10 border border-green-500/20 rounded-xl px-5 py-4 min-w-[160px]">
<i data-lucide="send" class="w-6 h-6 text-green-400 mx-auto mb-2"></i>
<div class="text-sm font-bold text-green-400">M4 Indexing</div>
<div class="text-[10px] text-slate-500 font-mono">Ping Google</div>
</div>
<i data-lucide="arrow-right" class="w-5 h-5 text-slate-600 hidden md:block"></i>
<i data-lucide="arrow-down" class="w-5 h-5 text-slate-600 md:hidden"></i>
<div class="bg-red-500/10 border border-red-500/20 rounded-xl px-5 py-4 min-w-[160px]">
<i data-lucide="radar" class="w-6 h-6 text-red-400 mx-auto mb-2"></i>
<div class="text-sm font-bold text-red-400">M6 SERP</div>
<div class="text-[10px] text-slate-500 font-mono">Surveillance</div>
</div>
</div>
</div>
</div>
</div>
<!-- Activity Log -->
<div class="bg-slate-900/50 border border-slate-800/80 rounded-xl backdrop-blur-sm overflow-hidden mb-6">
<div class="flex items-center justify-between px-5 py-3 border-b border-slate-800/60">
<div class="flex items-center gap-2">
<i data-lucide="terminal" class="w-4 h-4 text-indigo-400"></i>
<h2 class="text-sm font-semibold text-white">Journal Backend</h2>
</div>
<button onclick="clearLogs()" class="text-xs text-slate-500 hover:text-slate-300 transition-colors font-mono">CLEAR</button>
</div>
<div class="overflow-y-auto p-4 font-mono text-xs space-y-1.5" style="max-height: 220px;" id="activityLog"></div>
</div>
</div>
<!-- Toast -->
<div id="chsToast" class="fixed bottom-6 right-6 z-50 transform translate-y-20 opacity-0 transition-all duration-300">
<div class="bg-slate-900 border border-slate-700 rounded-xl px-4 py-3 shadow-2xl flex items-center gap-3">
<div class="w-8 h-8 bg-indigo-500/20 rounded-lg flex items-center justify-center">
<i data-lucide="check" class="w-4 h-4 text-indigo-400"></i>
</div>
<span class="text-sm font-medium text-slate-200" id="chsToastMsg">Done</span>
</div>
</div>
<script src="https://unpkg.com/lucide@latest"></script>
<script src="chs-backend.js"></script>
</body>
</html>