Skip to content

KeyCloakJS 使用

使用KeycloakJs来授权还是非常方便的,但是我们得首先了解授权码模式以及Pkce模式。

安装KeyCloak

可以利用docker安装Keycloak,详细可以参考这个官方进行配置 https://www.keycloak.org/getting-started/getting-started-docker

docker
docker pull keycloak/keycloak:22.0.4 

docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin keycloak/keycloak start-dev

然后根据官方的参考进行配置

KeyCloakJs

首先我们应该有一个基础的前端应用。这里我们选择react。我们使用lerna_demo来构建我们的keycloak js

一、初始化 KeyCloakClient 类, 这里重点关注的是new Keycloak实例的配置以及init的配置。

KeyCloak实例化有三个参数

  • clientId 配置的clientId
  • realm 配置的realm
  • url keycloak的url

KeyCloak init有以下配置

  • onLoad 该配置有 check-sso 以及 login-required

check-sso 是隐式的检查是否登录,如果没登录不会跳转到登录页面

login-required 检查是否登录,如果没登录就会跳转到登录页面

  • redirectUri 跳转uri

  • silentCheckSsoRedirectUri 如果是check-sso的时候默认查询登录,然后设置登录状态

typescript
import Keycloak, {
  KeycloakInitOptions,
  KeycloakLoginOptions,
  KeycloakLogoutOptions
} from 'keycloak-js'

export class KeycloakClient {
  private _keycloakClient: Keycloak
  constructor() {
    this._keycloakClient = new Keycloak({
      clientId: process.env.KEYCLOAK_CLIENT_ID!,
      realm: process.env.KEYCLOAK_RELEAM!,
      url: process.env.KEYCLOAK_URL
    })
  }

  getKeyCloakClient(): Keycloak {
    return this._keycloakClient
  }

  get authenticated() {
    return this._keycloakClient.authenticated
  }

  get userInfo() {
    return this._keycloakClient.userInfo
  }

  init(initOptions?: KeycloakInitOptions | undefined) {
    return this._keycloakClient.init({
      onLoad: 'check-sso',
      ...(initOptions ?? {})
    })
  }

  createLoginUrl(options?: KeycloakLoginOptions | undefined) {
    return this._keycloakClient.createLoginUrl(options)
  }

  logout = (options?: KeycloakLogoutOptions | undefined) => {
    return this._keycloakClient.logout(options)
  }
}

export const keyCloakClient = new KeycloakClient()

二、创建Login,Admin页面

创建Login页面,这里只有SSO登录,调用的是keyCloakClient的createLoginUrl,然后跳转

typescript
import React from 'react'
import Button from 'antd/es/button'
import { keyCloakClient } from '../keycloak'

export const LoginPage = () => {
  const onClickLoginSSO = () => {
    const url = keyCloakClient.createLoginUrl({
      redirectUri: window.location.origin + '/'
    })
    window.location.assign(url)
  }
  return <Button onClick={onClickLoginSSO}>Login with SSO</Button>
}

创建Admin页面, 只包含LogoutButton 和 展示用户名

typescript
import React, { FC } from 'react'
import { LogoutButton } from '../login'
import { keyCloakClient } from '../keycloak'

export const Admin: FC = () => {
  return (
    <div>
      Hello {keyCloakClient.getKeyCloakClient().idTokenParsed?.name ?? ''},
      welcome vist admin page.
      <LogoutButton />
    </div>
  )
}

三、配置路由

逻辑是如果访问根页面,判断是否登录,如果登录了,跳转admin,否则跳转login

同时如果直接访问admin,要判断是否已经登录,如果登录了可以跳转,否则提示未登录。

判断是否登录: keyCloakClient.authenticated

typescript
import React, { useMemo } from 'react'
import { createBrowserRouter, Navigate, RouterProvider } from 'react-router-dom'
import { LoginPage } from '../login'
import { Admin } from '../admin'
import { keyCloakClient } from '../keycloak'
import { ProtectedRouteElement } from './ProtectedRoute'

export const Routes = () => {
  const router = useMemo(() => {
    return createBrowserRouter([
      {
        path: '/',
        element: keyCloakClient.authenticated ? (
          <Navigate to='/admin' />
        ) : (
          <Navigate to='/login' />
        )
      },
      {
        path: '/login',
        element: <LoginPage />
      },
      {
        path: '/admin',
        element: (
          <ProtectedRouteElement>
            <Admin />
          </ProtectedRouteElement>
        )
      }
    ])
  }, [])

  return <RouterProvider router={router} />
}

四、初始化keyCloak

typescript
keyCloakClient.init().finally(() => {
  ReactDOM.render(<Index />, document.getElementById('content'))
})

上次更新于: