我正在将 keycloak-js 适配器与 Vue 3 应用程序一起使用。这个系统有一些公共页面,所以我不能立即调用keycloak。我已经设置了一个按钮来调用登录页面,但令牌尚未在 localStorage 中设置。
基本上我的用户流程需要是:登陆页面>单击登录按钮>转到keycloak登录页面>重定向到我请求返回用户角色的页面>获取用户行并重定向到正确的页面。
我的请求需要令牌,我可以访问重定向页面,但请求失败,因为我没有令牌或刷新令牌。另外,当我尝试不同的东西时,它会给出 TypeError:适配器未定义错误
这是我的 keycloak 初始化函数。如果我将 onLoad 选项更改为 check-sso,它将返回 #error=login_required&state=c7d6d227-5b23-4b21-962a-8e6291545f55。所以需要登录对我来说很有效。
const Login = () => {
KeyCloakInstance.init({ onLoad: "login-required", checkLoginIframe: true,
redirectUri: window.location.origin + "/redirect" })
.then((authenticated) => {
console.log("Keycloak Authenticated", authenticated)
if (authenticated) {
console.log("Authentication Success")
KeyCloakInstance.authenticated = true;
} else {
console.log("Authentication Failed")
}
localStorage.setItem('token', KeyCloakInstance.token as string);
localStorage.setItem('refreshToken', KeyCloakInstance.refreshToken as string);
}).catch((err) => {
console.dir(err);
console.log("Authentication Failed", err);
});
}
这是我为路线制作的守卫
import { getRole } from "@/services/config";
import Keycloak from "keycloak-js";
function guardAuth(to: any, from: any, next: any){
const hasUser = localStorage.getItem("token");
const isMeta = "auth" in to.meta;
const metaAuth = to.meta.auth;
if(isMeta && metaAuth && !hasUser){
const keycloakInst = new Keycloak({
url: "http://localhost:8082/",
realm: "APP",
clientId: "live_app"
});
keycloakInst.login();
} else if(isMeta && !metaAuth && hasUser){
RoleType(hasUser, next);
} else {
next();
}
}
function RoleType(user: any, next: any): void{
if(getRole() == user.role_portal){
next('/redirect');
} else {
next('/');
}
}
export { guardAuth };
我尝试更改 keycloak 初始化选项并为我的路线设置守卫,这样我可以检查是否有令牌,但它们似乎也不起作用。我希望有一个流程,其中一些页面是公开的,而其他页面则受 keycloak 保护
这就是我在 Vue.js 应用程序中设置 keycloak 的方式。我有两个页面是公开的,其余页面是私有的,需要在 keycloak 身份验证后才能访问。
import Keycloak from "keycloak-js";
import useStore from "./store";
const initOptions = {
realm: import.meta.env.VITE_KEYCLOAK_REALM_NAME,
clientId: import.meta.env.VITE_KEYCLOAK_CLIENT_ID,
url: import.meta.env.VITE_KEYCLOAK_SERVER_URL,
"public-client": true,
"verify-token-audience": false,
};
const keycloak = Keycloak(initOptions);
async function initKeycloak() {
const store = useStore();
await keycloak
.init({onLoad: "check-sso", redirectUri: import.meta.env.VITE_KEYCLOAK_REDIRECT_URI})
.then(async (auth) => {
if (!auth) {
store.unauthenticate();
} else {
await store.authenticate();
if (keycloak.token) {
store.token = keycloak.token;
store.userRoles = keycloak.tokenParsed.realm_access.roles;
window.localStorage.setItem("keycloakToken", keycloak.token);
}
}
});
setInterval(() => {
keycloak
.updateToken(70)
.then((refreshed) => {
if (refreshed) {
store.token = keycloak.token;
window.localStorage.setItem("keycloakToken", keycloak.token);
console.info("Token refreshed" + refreshed);
} else {
console.warn(
"Token not refreshed, valid for " +
Math.round(
keycloak.tokenParsed.exp +
keycloak.timeSkew -
new Date().getTime() / 1000
) +
" seconds"
);
}
})
.catch(() => {
console.error("Failed to refresh token");
});
}, 3000);
}
export async function keycloakLogin() {
keycloak.login();
}
// keycloak logout
var logoutOptions = {redirectUri: import.meta.env.VITE_KEYCLOAK_REDIRECT_URI};
function keycloakLogout() {
keycloak
.logout(logoutOptions)
.then((success) => {
console.log("--> log: logout success ", success);
})
.catch((error) => {
console.log("--> log: logout error ", error);
});
}
我不确定你为什么使用
KeycloakInstance
也许你已经在文件顶部声明了它。我只是在我的登陆页面上使用 keycloakLogin
方法,该方法是公开的并且具有登录按钮。
单击
login
按钮时,将调用 keycloakLogin
方法并重定向到 auth server
。身份验证成功后,它会重定向到我的 redirectUri
中存在的 .env
。
我希望这有帮助。
我有同样的问题,我发现使用 keycloak-js 的所有示例都通过调用 keycloak.init() 来保护每条路由,并根据成功情况进行应用程序渲染。因此,如果用户未登录,整个应用程序将不会呈现。
相反,我想使用 vue 路由器并拥有一些公共路由和其他私有路由。我想稍后仅在我决定时才调用 keycloak.init() ,但我被困了几个小时。我可以让用户通过 init() 函数进行连接,但是当在我的应用程序上重定向(使用我的重定向 uri)时,我无法获取用户/令牌信息,我只是被重定向并重新加载页面。
例如: 等待 keycloak.init({ onLoad: "需要登录", 重定向Uri:
${import.meta.env.VITE_APP_URL}
,
});
console.log(keycloak);
在这里,我的 console.log 从未显示,页面已重新加载,我可以看到会话在我的 keycloak 管理器中启动,但在我的 vue 应用程序中我无法使用该信息(比如将其放入 pinia 商店中)。
如果有人可以提供一些代码片段或解释,我们将不胜感激!