5

我正在我的 Angular 2 项目中实现 Keycloak 身份验证服务。我使用服务进行登录、注销等。

验证用户并注销似乎有效。我现在正试图保护一些路线。我现在有一个有效的 AuthGuard。为了检查用户是否登录(在 AuthGuard 中),我在服务中有一个 isAuthenticated() 方法。这是服务:

import { Injectable } from '@angular/core';

declare let Keycloak: any;

@Injectable()
export class KeycloakService {
  private keycloak = new Keycloak('app/keycloak/keycloak.json');

  constructor() {
    this.keycloak.init({onload: 'check-sso'});
    console.log(this.keycloak);
  }

  public login() {
    this.keycloak.login();
  }

  public logout() {
    this.keycloak.logout();
  }

  public isAuthenticated() {
    return this.keycloak.authenticated;
  }
}

流程:用户登录,用户尝试访问受保护的路由,AuthGuard 检查用户是否通过 isAuthenticated() 登录。

注意:我不想对完整的 Angular 应用程序的用户进行身份验证。仅适用于某些路线。

问题

用户登录后,用户被重定向到 Angular 应用程序。在此之后,isAuthenticated() 方法仍然返回 false。原因如下:

我将 Keycloak 对象记录到控制台。我发现了一些我不明白的东西。

登录重定向后的 Keycloak 对象

登录重定向后的 Keycloak 对象


登录重定向后相同的 Keycloak 对象(但已扩展)

登录重定向后相同的 Keycloak 对象(但已扩展)

首先认证的属性是假的。展开后验证属性为真。

问题

我尝试维护 Keycloak 对象的方式是否正确?

咨询来源

和别的

4

2 回答 2

5

根据社区在keycloak 的 github中提供的 Angular2 示例,您可以发现与 keycloak js 适配器交互的一些差异。主要是对经过身份验证的(可能还有用户名)的实际检查是在从 init 返回的承诺上完成的。

  static init(): Promise<any> {
    let keycloakAuth: any = new Keycloak('keycloak.json');
    KeycloakService.auth.loggedIn = false;

      return new Promise((resolve, reject) => {
        keycloakAuth.init({ onLoad: 'login-required' })
          .success(() => {
            KeycloakService.auth.loggedIn = true;
            KeycloakService.auth.authz = keycloakAuth;
            KeycloakService.auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/demo/protocol/openid-connect/logout?redirect_uri=/angular2-product/index.html";
            resolve();
          })
          .error(() => {
            reject();
          });
      });
}

官方keycloak js 适配器的文档也使用 promise 进行身份验证检查

<head>
    <script src="keycloak.js"></script>
    <script>
        var keycloak = Keycloak();
        keycloak.init().success(function(authenticated) {
            alert(authenticated ? 'authenticated' : 'not authenticated');
        }).error(function() {
            alert('failed to initialize');
        });
    </script>
</head>
于 2017-01-12T13:38:41.643 回答
1
  1. 如果您使用check-sso作为 init 函数的参数,如果用户未登录,浏览器将被路由回应用程序并保持未经身份验证。您应该使用login-required来解决此问题。

  2. 如果您不想为整个应用程序验证用户身份,则应分离创建适配器的逻辑,以便在您拥有多个安全组件时使事情变得更容易。例如,您可以创建一个HOC

PS:在下面的示例中,我使用的是 Reactjs,希望您能找到类似的方式来在 Angular 中执行此操作:

export default (WrappedComponent) => {
  return (props) => {
  const [isAutenticated, setIsAutenticated] = useState(false);
  const [keycloak, setKeycloak] = useState();

  const loadConfig = useCallback(() => {
    const keycloak = Keycloak("/keycloak.json"); //The configuration of the adapter in JSON format
    keycloak.init({ onLoad: "login-required" }).then((authenticated) => {
      setKeycloak(keycloak);
      setIsAutenticated(authenticated);
      });
  }, [Keycloak]);

  useEffect(() => {
    loadConfig();
  }, [loadConfig]);

  if (keycloak) {
    if (isAutenticated) {
      return <WrappedComponent {...props} keycloak={keycloak} />;
    } else return <AuthError message="Unable to authenticate" />;
  }
  return <Loader />;
  };
};
  1. 你可以在这里找到有用的资源
于 2020-07-11T15:22:23.807 回答