KeyCloak-js 和 vue3 - 需要一些页面公开

问题描述 投票:0回答:2

我正在将 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 保护

typescript vue.js vuejs3 keycloak keycloak-js
2个回答
1
投票

这就是我在 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

我希望这有帮助。


0
投票

我有同样的问题,我发现使用 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 商店中)。

如果有人可以提供一些代码片段或解释,我们将不胜感激!

© www.soinside.com 2019 - 2024. All rights reserved.