diff --git a/pom.xml b/pom.xml index 314fe92..814576f 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ 17 17 - 26.2.4 + 26.4.2 UTF-8 diff --git a/src/main/java/top/ysit/qrlogin/core/QRSession.java b/src/main/java/top/ysit/qrlogin/core/QRSession.java index 5a1ad0b..5f7b928 100644 --- a/src/main/java/top/ysit/qrlogin/core/QRSession.java +++ b/src/main/java/top/ysit/qrlogin/core/QRSession.java @@ -86,4 +86,6 @@ public class QRSession { public void setResponseUrl(String responseUrl) { this.responseUrl = responseUrl; } + + } \ No newline at end of file diff --git a/src/main/java/top/ysit/qrlogin/core/util/TokenUtil.java b/src/main/java/top/ysit/qrlogin/core/util/TokenUtil.java index 022c56d..a2c71d0 100644 --- a/src/main/java/top/ysit/qrlogin/core/util/TokenUtil.java +++ b/src/main/java/top/ysit/qrlogin/core/util/TokenUtil.java @@ -18,7 +18,7 @@ public class TokenUtil { if (token == null || token.isEmpty()) { return TokenValidationResult.invalid("token 为空或无效"); } - if (config.baseUrl == null || config.realm == null || config.clientId == null || config.clientSecret == null){ + if (config.baseUrl == null || config.realm == null || config.clientId == null || config.clientSecret == null) { return TokenValidationResult.invalid("配置错误"); } @@ -62,8 +62,6 @@ public class TokenUtil { JsonObject payload = tokenToJson(token); String email = payload.getString("email", null); String sub = json.getString("sub", null); - - return TokenValidationResult.valid(username, clientId, email, sub, scope, exp); } catch (Exception e) { @@ -82,7 +80,6 @@ public class TokenUtil { if (token == null || token.isEmpty()) { return null; } - try { // JWT token 由三部分组成,用点分隔:header.payload.signature String[] parts = token.split("\\."); @@ -103,7 +100,8 @@ public class TokenUtil { } // Base64 解码 - byte[] decodedBytes = java.util.Base64.getDecoder().decode(payload); + // 使用URL安全的Base64解码器 + byte[] decodedBytes = java.util.Base64.getUrlDecoder().decode(payload); String decodedString = new String(decodedBytes, StandardCharsets.UTF_8); // 解析为 JsonObject diff --git a/src/main/java/top/ysit/qrlogin/idp/QRLoginIdentityProvider.java b/src/main/java/top/ysit/qrlogin/idp/QRLoginIdentityProvider.java index 503e240..38f4ed0 100644 --- a/src/main/java/top/ysit/qrlogin/idp/QRLoginIdentityProvider.java +++ b/src/main/java/top/ysit/qrlogin/idp/QRLoginIdentityProvider.java @@ -12,7 +12,9 @@ import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; +import org.keycloak.services.managers.AuthenticationSessionManager; import org.keycloak.sessions.AuthenticationSessionModel; +import org.keycloak.sessions.RootAuthenticationSessionModel; import org.keycloak.util.JsonSerialization; import org.keycloak.utils.MediaType; import top.ysit.qrlogin.config.QRLoginConfig; @@ -71,6 +73,7 @@ public class QRLoginIdentityProvider extends AbstractIdentityProvider { if (expired) return; try { const resp = await fetch(`${statusUrl}${statusUrl.includes('?') ? '&' : '?'}timestamp=${Math.floor(Date.now() / 1000)}`); + // 检查HTTP状态码,处理404等情况 + if (!resp.ok) { + if (resp.status === 404) { + // 处理404错误,视为二维码失效 + handleQRCodeExpired(); + return; + } else { + throw new Error(`HTTP error! status: ${resp.status}`); + } + } + const data = await resp.json(); + switch (data.status) { case "CONFIRMED": const url = data.url; @@ -121,5 +133,24 @@ document.addEventListener("DOMContentLoaded", () => { } }; poll(); + const handleQRCodeExpired = () => { + expired = true; + tip.innerText = "二维码已失效,请重新开始登录流程"; + tip.style.color = "#dc3545"; + count.style.display = "none"; + + // 模糊二维码图像 + const qrImage = box.querySelector('img'); + if (qrImage) { + qrImage.style.filter = "blur(4px)"; + } + + btn.innerText = "重新开始"; + btn.style.background = "#007bff"; + btn.onclick = () => { + window.location.reload(); + }; + }; }); + });