使用 Webfilter 时 Keycloak 刷新过期令牌
Keycloak refresh expired token when using Webfilter
我遇到了一个问题,我认为我的访问令牌需要一个可调整的到期时间。我 运行 在 glassfish 服务器上使用 org.keycloak.adapters.servlet.KeycloakOIDCFilter 检查所有请求。我设置的过滤器检查 AccessToken 并通过确保令牌未过期来询问访问权限:
KeycloakSecurityContext kc = (KeycloakSecurityContext) req
.getAttribute(KeycloakSecurityContext.class.getName());
AccessToken token = RSATokenVerifier.create(kc.getIdTokenString()).getToken();
if(token.isExpired()) {
response.redirect("logout url");
}
这很好用。但是,在我的应用程序中,我有一些屏幕,用户可以在其中花费长达一个小时的时间输入信息,在这些屏幕上,他们可能会在完成提供糟糕的用户体验之前被踢出。在某些情况下,正在进行 ajax 调用并且响应设置为重定向到导致不良行为的注销页面。
我真的认为我需要始终检查过期时间,但我不确定如何在过期时请求新令牌。我感谢我能得到的任何帮助。谢谢!
这些是我的令牌设置
您还需要有权访问刷新令牌。一旦访问令牌过期,您将无能为力。我将在下面留下我们应用程序中的示例。
URL url = new URL(keycloakRootURL + "/realms/" + realmName + "/protocol/openid-connect/token");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "Basic " + clientSecret);
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
String data = "grant_type=refresh_token&refresh_token=" + refreshToken;
try (OutputStream os = conn.getOutputStream(); BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"))) {
writer.write(data);
writer.flush();
}
conn.connect();
StringBuilder responseStr;
try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
String inputLine;
responseStr = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
responseStr.append(inputLine);
}
}
Object obj = parser.parse(responseStr.toString());
JSONObject result = (JSONObject) obj;
accessCreationTime = System.nanoTime();
return (String) result.get("access_token");
注销运行良好的密钥斗篷:
public static void keycloakLogout(HttpServletRequest request, HttpSession session) {
SerializableKeycloakAccount keycloakAccount = (SerializableKeycloakAccount) session
.getAttribute(KeycloakAccount.class.getName());
if (keycloakAccount != null && keycloakAccount instanceof SerializableKeycloakAccount) {
RefreshableKeycloakSecurityContext ksc = keycloakAccount.getKeycloakSecurityContext();
KeycloakDeployment deployment = ksc.getDeployment();
// KeycloakDeployment deployment =
// keycloakAccount.getKeycloakSecurityContext().getDeployment();
if (deployment != null) {
ksc.logout(deployment);
// keycloakAccount.getKeycloakSecurityContext().logout(deployment);
request.removeAttribute(KeycloakSecurityContext.class.getName());
session.removeAttribute(TOKEN_KEY);
}
}
}
登录时设置TOKEN_KEY
session.setAttribute(TOKEN_KEY, keycloakToken);
我遇到了一个问题,我认为我的访问令牌需要一个可调整的到期时间。我 运行 在 glassfish 服务器上使用 org.keycloak.adapters.servlet.KeycloakOIDCFilter 检查所有请求。我设置的过滤器检查 AccessToken 并通过确保令牌未过期来询问访问权限:
KeycloakSecurityContext kc = (KeycloakSecurityContext) req
.getAttribute(KeycloakSecurityContext.class.getName());
AccessToken token = RSATokenVerifier.create(kc.getIdTokenString()).getToken();
if(token.isExpired()) {
response.redirect("logout url");
}
这很好用。但是,在我的应用程序中,我有一些屏幕,用户可以在其中花费长达一个小时的时间输入信息,在这些屏幕上,他们可能会在完成提供糟糕的用户体验之前被踢出。在某些情况下,正在进行 ajax 调用并且响应设置为重定向到导致不良行为的注销页面。
我真的认为我需要始终检查过期时间,但我不确定如何在过期时请求新令牌。我感谢我能得到的任何帮助。谢谢!
这些是我的令牌设置
您还需要有权访问刷新令牌。一旦访问令牌过期,您将无能为力。我将在下面留下我们应用程序中的示例。
URL url = new URL(keycloakRootURL + "/realms/" + realmName + "/protocol/openid-connect/token");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "Basic " + clientSecret);
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
String data = "grant_type=refresh_token&refresh_token=" + refreshToken;
try (OutputStream os = conn.getOutputStream(); BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"))) {
writer.write(data);
writer.flush();
}
conn.connect();
StringBuilder responseStr;
try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
String inputLine;
responseStr = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
responseStr.append(inputLine);
}
}
Object obj = parser.parse(responseStr.toString());
JSONObject result = (JSONObject) obj;
accessCreationTime = System.nanoTime();
return (String) result.get("access_token");
注销运行良好的密钥斗篷:
public static void keycloakLogout(HttpServletRequest request, HttpSession session) {
SerializableKeycloakAccount keycloakAccount = (SerializableKeycloakAccount) session
.getAttribute(KeycloakAccount.class.getName());
if (keycloakAccount != null && keycloakAccount instanceof SerializableKeycloakAccount) {
RefreshableKeycloakSecurityContext ksc = keycloakAccount.getKeycloakSecurityContext();
KeycloakDeployment deployment = ksc.getDeployment();
// KeycloakDeployment deployment =
// keycloakAccount.getKeycloakSecurityContext().getDeployment();
if (deployment != null) {
ksc.logout(deployment);
// keycloakAccount.getKeycloakSecurityContext().logout(deployment);
request.removeAttribute(KeycloakSecurityContext.class.getName());
session.removeAttribute(TOKEN_KEY);
}
}
}
登录时设置TOKEN_KEY
session.setAttribute(TOKEN_KEY, keycloakToken);