keycloak界面配置及认证流程详解

界面上的字段和一些术语不懂的话可以自己百度。由于https需要证书不方便postman展示,所以使用http

keycloak设置master登录用户

在这里插入图片描述

keycloak 管理界面

在这里插入图片描述

keycloak 获取用户token

  1. 创建我们自己的域
    在这里插入图片描述

  2. 添加域的用户
    在这里插入图片描述

  3. 设置密码
    在这里插入图片描述

  4. 创建client(普通用户登录 设置public)
    在这里插入图片描述

  5. 查看openid配置详情
    接口:http://localhost:8080/auth/realms/{创建的realm名字}/.well-known/openid-configuration
    示例:http://localhost:8080/auth/realms/keycloak-manage-user/.well-known/openid-configuration

{
    "issuer": "http://localhost:8080/auth/realms/keycloak-manage-user",
    "authorization_endpoint": "http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/auth",
    "token_endpoint": "http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/token",
    "token_introspection_endpoint": "http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/token/introspect",
    "userinfo_endpoint": "http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/userinfo",
    "end_session_endpoint": "http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/logout",
    "jwks_uri": "http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/certs",
    "check_session_iframe": "http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/login-status-iframe.html",
    "grant_types_supported": [
        "authorization_code",
        "implicit",
        "refresh_token",
        "password",
        "client_credentials"
    ],
    "response_types_supported": [
        "code",
        "none",
        "id_token",
        "token",
        "id_token token",
        "code id_token",
        "code token",
        "code id_token token"
    ],
    "subject_types_supported": [
        "public",
        "pairwise"
    ],
    "id_token_signing_alg_values_supported": [
        "PS384",
        "ES384",
        "RS384",
        "HS256",
        "HS512",
        "ES256",
        "RS256",
        "HS384",
        "ES512",
        "PS256",
        "PS512",
        "RS512"
    ],
    "id_token_encryption_alg_values_supported": [
        "RSA-OAEP",
        "RSA1_5"
    ],
    "id_token_encryption_enc_values_supported": [
        "A128GCM",
        "A128CBC-HS256"
    ],
    "userinfo_signing_alg_values_supported": [
        "PS384",
        "ES384",
        "RS384",
        "HS256",
        "HS512",
        "ES256",
        "RS256",
        "HS384",
        "ES512",
        "PS256",
        "PS512",
        "RS512",
        "none"
    ],
    "request_object_signing_alg_values_supported": [
        "PS384",
        "ES384",
        "RS384",
        "HS256",
        "HS512",
        "ES256",
        "RS256",
        "HS384",
        "ES512",
        "PS256",
        "PS512",
        "RS512",
        "none"
    ],
    "response_modes_supported": [
        "query",
        "fragment",
        "form_post"
    ],
    "registration_endpoint": "http://localhost:8080/auth/realms/keycloak-manage-user/clients-registrations/openid-connect",
    "token_endpoint_auth_methods_supported": [
        "private_key_jwt",
        "client_secret_basic",
        "client_secret_post",
        "tls_client_auth",
        "client_secret_jwt"
    ],
    "token_endpoint_auth_signing_alg_values_supported": [
        "PS384",
        "ES384",
        "RS384",
        "HS256",
        "HS512",
        "ES256",
        "RS256",
        "HS384",
        "ES512",
        "PS256",
        "PS512",
        "RS512"
    ],
    "claims_supported": [
        "aud",
        "sub",
        "iss",
        "auth_time",
        "name",
        "given_name",
        "family_name",
        "preferred_username",
        "email",
        "acr"
    ],
    "claim_types_supported": [
        "normal"
    ],
    "claims_parameter_supported": false,
    "scopes_supported": [
        "openid",
        "address",
        "email",
        "microprofile-jwt",
        "offline_access",
        "phone",
        "profile",
        "roles",
        "web-origins"
    ],
    "request_parameter_supported": true,
    "request_uri_parameter_supported": true,
    "code_challenge_methods_supported": [
        "plain",
        "S256"
    ],
    "tls_client_certificate_bound_access_tokens": true,
    "introspection_endpoint": "http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/token/introspect"
}

大家看着理解,不懂的留言,这里面列举了openid支持的配置uma后面讲
6. 获取public client 用户token
“token_endpoint”: “http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/token”

curl --location --request POST 'http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=test' \
--data-urlencode 'password=123456' \
--data-urlencode 'client_id=user-token' \
--data-urlencode 'grant_type=password'
{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJjQ3JWRXFCYUNxcG1vcFNTMFpicVozeGsydWdUT2NRQ19NLVV0NkVBWWlzIn0.eyJqdGkiOiJhNzkzMzM3MS0wNzVkLTQ2ZTctYjYzYS05NDQ2NDZhNjk1MDgiLCJleHAiOjE1ODgyMzA2OTksIm5iZiI6MCwiaWF0IjoxNTg4MjMwMzk5LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMva2V5Y2xvYWstbWFuYWdlLXVzZXIiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiZjcxMDgzZTctNGUxYy00NmU2LWJkNjYtMTQ5Yjg3ZDIxNWRhIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidXNlci10b2tlbiIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjUwMzU3OWZmLWZlMDUtNDZmMi04YjQ2LWU3MWE4M2RkNmFkNyIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDo4MDgwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0In0.TICwaP0N00YnSk_RNYZOM9miF_Bx8PZqsR-h91vdGr6lFlxSVSIspLzwRjM1oZ5NDcbEJvD43Nirn5L3aoVzdFoPWU2dEIO8Py_TiONCc1UPmzE9HJ2OudhcVc7tMCPnhm3QKJ1df3QO7icz0ErHrpBdcxjAjt9wLipxjgPF96Mdif1kvLeDmSCz4-adgWk2OHlaiGsjfuoWTliWHS5nY_92c3w2wglrplB-6UF11khR70-wZWYaxT1I85FiD9cJ9UaW2tnehPyNenGvi7n5PTEEraDtYxxgnEn6bXYXeBfor9hPs6rVuMyguBHqRSPexVnbcrdB3caHQKLnVfEF2A",
    "expires_in": 300,
    "refresh_expires_in": 1800,
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI3NWNiZjc2ZC0zNzkwLTRiMjYtYTRjMi0wMmQ0YjZkMjlhNmUifQ.eyJqdGkiOiJmMzNlZWE2MC1jMTM4LTQ5OGEtYmM4Yy1mZTE3YTkyMzNiZmMiLCJleHAiOjE1ODgyMzIxOTksIm5iZiI6MCwiaWF0IjoxNTg4MjMwMzk5LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMva2V5Y2xvYWstbWFuYWdlLXVzZXIiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMva2V5Y2xvYWstbWFuYWdlLXVzZXIiLCJzdWIiOiJmNzEwODNlNy00ZTFjLTQ2ZTYtYmQ2Ni0xNDliODdkMjE1ZGEiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoidXNlci10b2tlbiIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjUwMzU3OWZmLWZlMDUtNDZmMi04YjQ2LWU3MWE4M2RkNmFkNyIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIn0.FwDKqA3l-ZA3i8WBIur8lQ6LRkw7HHZNWgzgj8Wbs5Y",
    "token_type": "bearer",
    "not-before-policy": 0,
    "session_state": "503579ff-fe05-46f2-8b46-e71a83dd6ad7",
    "scope": "email profile"
}
  1. 用户token解析
curl --location --request POST 'http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/userinfo' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'access_token=eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJjQ3JWRXFCYUNxcG1vcFNTMFpicVozeGsydWdUT2NRQ19NLVV0NkVBWWlzIn0.eyJqdGkiOiI3MjUwNjU2Zi1jNGY0LTQ2NWUtYjFmNC02MmU5Yzk2ODA0NzYiLCJleHAiOjE1ODgyMzExODcsIm5iZiI6MCwiaWF0IjoxNTg4MjMwODg3LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMva2V5Y2xvYWstbWFuYWdlLXVzZXIiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiZjcxMDgzZTctNGUxYy00NmU2LWJkNjYtMTQ5Yjg3ZDIxNWRhIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidXNlci10b2tlbiIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjhmNzJmMjU3LTg4ZTAtNDE5Ni1hZDllLTIyOGJjZDE1ZTU2NCIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDo4MDgwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0In0.ZSfY_SouVSxcLsloQl8h1KEzH1TnrJvMT3bkcK0X116kq6M3Oa43tiUm4NYOxSDqg5L9nwbVaVaFrE7_n1M6V392sl1zhZljmKldsSHzUGzuk5gIk50LckDNC160YBpFgv8yBb_E_NTWcymp71q90IuZ36QgnbgDpxl5r_RrKjcuZMrzje5LGhVSI4FXyS3Ed--pP7GHSG8Rd1vAhvL4ZEsTNq5brwKaREmiNV0w959E78nB4SUWAdY0H8H2J7umaFUUMpFh4MgIdYl6iZTKIqXymxrnEhLcVWEqVDYHf1L097fqijW7QBxFjMihAca4QWxF2zoKguDJq5x5paQQWw'

在这里插入图片描述
8. confidential client 设置
在这里插入图片描述
public confidential 区别:
public 就是简单的账号密码登录
confidential 需要算法支持
从配置中可以看到支持5种:

     "private_key_jwt",
     "client_secret_basic",
     "client_secret_post",
     "tls_client_auth",
     "client_secret_jwt"
  1. client_secret 方式获取用户token
    在这里插入图片描述
curl --location --request POST 'http://localhost:8080/auth/realms/keycloak-manage-user/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=user-token' \
--data-urlencode 'client_secret=40bf9908-94e1-4571-8ad3-10940e21ee9f' \
--data-urlencode 'username=test' \
--data-urlencode 'password=123456'

注意grant_type=client_credentials参数的修改
10. client 认证 "client_secret_post " 获取client token
在这里插入图片描述
在这里插入图片描述
这里新建了realm和client方便区分

curl --location --request POST 'http://localhost:8080/auth/realms/openbanking/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=client1-mtls-PS256-PS256' \
--data-urlencode 'client_secret=63795b52-65ec-468c-a7b9-4b73817bdfc9' \
--data-urlencode 'grant_type=client_credentials'
  1. client 认证 “client_secret_basic” 获取client token
    在这里插入图片描述

在这里插入图片描述

curl --location --request POST 'http://localhost:8080/auth/realms/openbanking/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic Y2xpZW50MS1tdGxzLVBTMjU2LVBTMjU2OjYzNzk1YjUyLTY1ZWMtNDY4Yy1hN2I5LTRiNzM4MTdiZGZjOQ==' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=client1-mtls-PS256-PS256' \
--data-urlencode 'scope=accounts'

Base64.getEncoder().encodeToString((id + “:” + secret).getBytes());
13. client 认证 “private_key_jwt” 获取client token
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(1) 使用java代码生成公钥私钥
参考:https://connect2id.com/products/nimbus-jose-jwt/examples/jwt-with-rsa-signature

      <dependency>
            <groupId>com.nimbusds</groupId>
            <artifactId>nimbus-jose-jwt</artifactId>
            <version>${nimbus-version}</version>
        </dependency>
       <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>${bcprov-version}</version>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.14</version>
        </dependency>
        
         <nimbus-version>7.0</nimbus-version>
        <gson-version>2.8.4</gson-version>
        <bcprov-version>1.60</bcprov-version>
         RSAKey privateKey = new RSAKeyGenerator(2048)
                .algorithm(JWSAlgorithm.PS256)
                .keyUse(KeyUse.SIGNATURE)
                .keyID("client-PS256")
                .generate();
        RSAKey publicKey = privateKey.toPublicJWK();

生成的私钥

{
    "keys": [
        {
            "p": "77_7i2uGN6RxaCU6m217guw2gdLeknEbi34IeJpvK5xqufrs00aMCqnCXwWAEsqCm3CmITdhTPNZSemETcsouW82NiHQ_cbI7agNpAaTU6kRdzaOVyJSJgs-pmxgFMbgkBmIHZbbtdrpIykTHlhmilPnRhQvwN3N_7eymmbXPe0", 
            "kty": "RSA", 
            "q": "nbVbCk7BMP1syPPR0IUbDwYmLkFnUL6TXgXA4o-3IIdP-bFJKc2ONTxtsLl-Q-H2dDKugjHe-AyVvVRmiMUna2VVEUbG3I6z0mvok19fC9Gd7kCalJuXfNBnJVyoJfCfOmDn3RepYUP7mWUAmlbtMxbud0-F90T60vIgewPN7e0", 
            "d": "COuCJEsUHUcg39kF9S9cTt8GsaxIEP-vqI9GonGz_nC3uBFDRhyqGKj-JWWoG3Vso3i658bnJdMf1aW4KjxJon-D0nfAAZXPUj7OfJZ__D874BKRSg9NqE7uubsU3ByPvLVexqsGAy4tRCM14zwXpNM_YAe0z7c4tmSrDmUdFZUpt8YhL33jPi5KDaxtEdMrbL2OKIdrolJjJnX7loVJcSneM7bXvx-6ieDfO8HgMlmnpik3t_9HVeJ1-o30ndv5KsVG1i7NtTDgAGTqbInHD7WdRLIzgTbXTmoAWY4ccHeDNzh6S_9jKk_sQE9A1oLFUmL-7qtk8qnl9ZBDoxGIYQ", 
            "e": "AQAB", 
            "use": "sig", 
            "kid": "client-PS256", 
            "qi": "AiADA77A6JGn1iOEd2CM0c17LK6AzpGkVUzMfI_yoIzwpaJh41zd77nO_xe49e0FQNEEIjh__C4svctz7RA_90pteFDQ8TBoSmm8j6Jb-BdaDVIt_Ax77RRAiPD5ZSSqj-XzkjIUCNjghWjDz6H_k1FbcBA-lTBaia1tvioWh7A", 
            "dp": "vue3TBAlgr8Nkqk6XrMyC1E-IeggVKl-DnggFLCcXzShA1CcLavaLU95t6IwlkXs9AsiLgbkEpsfeSxZrnxcBDRbDYWl3b3hFuSfYAHgZFiW0L9_XkC0-xgvHePkKgcmn3fFHBKZBti2lcnKMHqhw_oFiZbfY4r60mma7TmAoQ0", 
            "alg": "PS256", 
            "dq": "O75nNblt8Fwg6OOM2VyDSqa-sgku1WTMuPKfBnUBH76C6olhuQdY1wwEVc1_asHgNla4yzOPTxKdazLdAPUHIOUrW7cfQJCCyLT-T03y2KxZEtfAd4mV0r-0Q3Addvn3qArr61K6ZNF3L74Wg2FozFDkl6g1jN3B00XMTi27xmU", 
            "n": "k7KVREAwJPKOfJC9Q71ZA3MZyZpv2S0wRDtz4wurqu2kNNd33-pIAkUABnSFDWxHdrXF0lL6fBJ558f5ybLk4rXE4dT0UJQLYxjBONoilkOIbZhXvtd-GWRy6bzmuRMBgUzvULTjCXSUpyllche6uStZFMRrlrRaZYGU1K0MNGmC6VzbKyYU8SJg9T9OupdtVSA0zmRtMeI7tk8-vQceonStkNrBklJ_pbqtFh-UpqRlZABJ-UqTNRY3Cm2x8X_QaEzGA-3eeRk4uNLTPVdgOOKven0lZdePRtdCowfXRxVwGrFGINonZn--gqlVc6rqo2KRIJgSTWXndIsb12G9aQ"
        }
    ]
}

公钥

{
    "keys": [
        {
            "kty": "RSA", 
            "e": "AQAB", 
            "use": "sig", 
            "kid": "client-PS256", 
            "alg": "PS256", 
            "n": "k7KVREAwJPKOfJC9Q71ZA3MZyZpv2S0wRDtz4wurqu2kNNd33-pIAkUABnSFDWxHdrXF0lL6fBJ558f5ybLk4rXE4dT0UJQLYxjBONoilkOIbZhXvtd-GWRy6bzmuRMBgUzvULTjCXSUpyllche6uStZFMRrlrRaZYGU1K0MNGmC6VzbKyYU8SJg9T9OupdtVSA0zmRtMeI7tk8-vQceonStkNrBklJ_pbqtFh-UpqRlZABJ-UqTNRY3Cm2x8X_QaEzGA-3eeRk4uNLTPVdgOOKven0lZdePRtdCowfXRxVwGrFGINonZn--gqlVc6rqo2KRIJgSTWXndIsb12G9aQ"
        }
    ]
}

公钥导入到kecloak中 私钥进行加密
在这里插入图片描述
在这里插入图片描述
私钥加密过程
参考:https://tools.ietf.org/html/rfc7523

      Provider bc = BouncyCastleProviderSingleton.getInstance();
        Security.addProvider(bc);
        //        iss:client1-mtls-PS256-PS256
//        sub:client1-mtls-PS256-PS256
//        aud:http://192.168.11.63:8080/auth/realms/openbanking/protocol/openid-connect/token
//        jti:bMLxAT7Kw0xhDN2ughzy
//        iat:Long.toString(new Date(System.currentTimeMillis()).getTime()
//        exp:Long.toString(new Date(System.currentTimeMillis() + 30 * 60 * 1000).getTime()
        BufferedReader reader = new BufferedReader(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("ps256jwt.json"), "UTF-8"));
        StringBuilder sb = new StringBuilder();
        String s; // 依次循环,至到读的值为空
        while ((s = reader.readLine()) != null) {
            sb.append(s);
        }
        reader.close();
        String jwks = sb.toString();
        JsonObject claims = new JsonObject();
        claims.addProperty("iss", "client-PS256");
        claims.addProperty("sub", "client-PS256");
        claims.addProperty("aud", "http://localhost:8080/auth/realms/openbanking/protocol/openid-connect/token");
        claims.addProperty("jti", RandomStringUtils.randomAlphanumeric(20));
        Instant iat = Instant.now();
        Instant exp = iat.plusSeconds(60);
        claims.addProperty("iat", iat.getEpochSecond());
        claims.addProperty("exp", exp.getEpochSecond());
        JWTClaimsSet claimSet = JWTClaimsSet.parse(claims.toString());
        JWKSet jwkSet = JWKSet.parse(jwks.toString());
        SignedJWT assertion = null;
        if (jwkSet.getKeys().size() == 1) {
            // figure out which algorithm to use
            JWK jwk = jwkSet.getKeys().iterator().next();
            JWSSigner signer = null;
            if (jwk.getKeyType().equals(KeyType.RSA)) {
                signer = new RSASSASigner((RSAKey) jwk);
            } else if (jwk.getKeyType().equals(KeyType.EC)) {
                signer = new ECDSASigner((ECKey) jwk);
            } else if (jwk.getKeyType().equals(KeyType.OCT)) {
                signer = new MACSigner((OctetSequenceKey) jwk);
            }
            Algorithm alg = jwk.getAlgorithm();
            JWSHeader header = new JWSHeader(JWSAlgorithm.parse(alg.getName()), null, null, null, null, null, null, null, null, null, jwk.getKeyID(), null, null);
            assertion = new SignedJWT(header, claimSet);
            assertion.sign(signer);
        }
        System.out.println(assertion.serialize());
    }

client_assertion

eyJraWQiOiJjbGllbnQtUFMyNTYiLCJhbGciOiJQUzI1NiJ9.eyJzdWIiOiJjbGllbnQtUFMyNTYiLCJhdWQiOiJodHRwOlwvXC9sb2NhbGhvc3Q6ODA4MFwvYXV0aFwvcmVhbG1zXC9vcGVuYmFua2luZ1wvcHJvdG9jb2xcL29wZW5pZC1jb25uZWN0XC90b2tlbiIsImlzcyI6ImNsaWVudC1QUzI1NiIsImV4cCI6MTU5MDcxODAwOSwiaWF0IjoxNTkwNzE3OTQ5LCJqdGkiOiJtUk9lU2p6V2tHU0FCaFRwU3V0dCJ9.anYhhS5CGUXLmQN7VJkVmVqajVLKO62t48yLlp0WPYMRn9rQp7-RpTTVYRctHcLSN5INGbIjO8jJjAl5M3jpE5vGcOa-bzHWJiTGxxwUevwRVru9oCaVdd9ESBH9TOMuiaQyzHCZI5m8uWg_3TSzXxk9p3yAh8SswTEiOuSPGW7EvRZ8T_Q_z_hnJrUqGqYYodMxook1YtZ1TsX58UexbKKXpTLZpTPGaYWkY-DJoQ5_B8vupmcydSgVMH30Z-xpRcHL497l2R3zLBVi5wC1e7zIbVUcKjMaKC7-JpFafeTNFXAorfQ8TD0jYCCTJLZA34ntulRoJ8ptvZs3CGiaPA

curl命令

curl --location --request POST 'http://localhost:8080/auth/realms/openbanking/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=client-PS256' \
--data-urlencode 'client_secret=9563616a-31d2-45ce-94a2-c0109963a134' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode 'client_assertion=eyJraWQiOiJjbGllbnQtUFMyNTYiLCJhbGciOiJQUzI1NiJ9.eyJzdWIiOiJjbGllbnQtUFMyNTYiLCJhdWQiOiJodHRwOlwvXC9sb2NhbGhvc3Q6ODA4MFwvYXV0aFwvcmVhbG1zXC9vcGVuYmFua2luZ1wvcHJvdG9jb2xcL29wZW5pZC1jb25uZWN0XC90b2tlbiIsImlzcyI6ImNsaWVudC1QUzI1NiIsImV4cCI6MTU5MDcxODAwOSwiaWF0IjoxNTkwNzE3OTQ5LCJqdGkiOiJtUk9lU2p6V2tHU0FCaFRwU3V0dCJ9.anYhhS5CGUXLmQN7VJkVmVqajVLKO62t48yLlp0WPYMRn9rQp7-RpTTVYRctHcLSN5INGbIjO8jJjAl5M3jpE5vGcOa-bzHWJiTGxxwUevwRVru9oCaVdd9ESBH9TOMuiaQyzHCZI5m8uWg_3TSzXxk9p3yAh8SswTEiOuSPGW7EvRZ8T_Q_z_hnJrUqGqYYodMxook1YtZ1TsX58UexbKKXpTLZpTPGaYWkY-DJoQ5_B8vupmcydSgVMH30Z-xpRcHL497l2R3zLBVi5wC1e7zIbVUcKjMaKC7-JpFafeTNFXAorfQ8TD0jYCCTJLZA34ntulRoJ8ptvZs3CGiaPA'

返回结果

{
    "access_token": "eyJhbGciOiJQUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxaGdobFlJUURabU13cVpHbS1HSlFmUGJfU3NnWmk5UWV2Y0tYWFFTUTRVIn0.eyJqdGkiOiJiNDk2OTI4Yy0zZDZmLTQwZDUtYTcwOS00NTZhYjEwNzhkYzciLCJleHAiOjE1OTA3MTgyODEsIm5iZiI6MCwiaWF0IjoxNTkwNzE3OTgxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvb3BlbmJhbmtpbmciLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiY2M5NTA5M2ItZDM2YS00ZWQ5LWFhZDQtZTVkMDAxZGY3NmRkIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiY2xpZW50LVBTMjU2IiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiZjA4YmZmMGEtNzhkOC00MTI3LWJiYmMtNGRhZGZhNTRjZTcxIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjgwODAiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJjbGllbnQtUFMyNTYiOnsicm9sZXMiOlsidW1hX3Byb3RlY3Rpb24iXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsImNsaWVudElkIjoiY2xpZW50LVBTMjU2IiwiY2xpZW50SG9zdCI6IjEyNy4wLjAuMSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicHJlZmVycmVkX3VzZXJuYW1lIjoic2VydmljZS1hY2NvdW50LWNsaWVudC1wczI1NiIsImNsaWVudEFkZHJlc3MiOiIxMjcuMC4wLjEiLCJlbWFpbCI6InNlcnZpY2UtYWNjb3VudC1jbGllbnQtcHMyNTZAcGxhY2Vob2xkZXIub3JnIn0.k4tENDhWlOTUgJmHO7WHKBNc34KgqW2Cpuo04aeIJXDePTZr4FaC5HlcenfBUQpXwkEnaAuYVA08wIcUAVXRfpUbhRBZmZGNGcclfz3BqTQ8XH5lAiIslVHqJtDDExcADbUXjgv2PASlPSCI7LXy5vLNqO2AIvG-8mFXEx7r5NbIcu12AiZMwXPQYYlWq4iWAx6Zm_LyFoLjKAEvCO5gKNpXAeCDM-UkalGA9JqmFcjRimW_k8p8JGvLpUZiTxYozlTSFcViBm2RkCR2jQjzIgw2o1C2nNwqsp11fHiKCGr9cCRtD_9V33MePv3X8vxPMG3tv0npAY3DdNR_yTDJNw",
    "expires_in": 300,
    "refresh_expires_in": 1800,
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIwOGYxYmUyMC04ODU0LTRlYzQtYTllZi1jYTkyOTYzZTY4YmIifQ.eyJqdGkiOiI4YjQ0OWMzYS0yNzM3LTQxNTQtOGRjZi01YThlN2NmMGM3NzkiLCJleHAiOjE1OTA3MTk3ODEsIm5iZiI6MCwiaWF0IjoxNTkwNzE3OTgxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvb3BlbmJhbmtpbmciLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvb3BlbmJhbmtpbmciLCJzdWIiOiJjYzk1MDkzYi1kMzZhLTRlZDktYWFkNC1lNWQwMDFkZjc2ZGQiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiY2xpZW50LVBTMjU2IiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiZjA4YmZmMGEtNzhkOC00MTI3LWJiYmMtNGRhZGZhNTRjZTcxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJjbGllbnQtUFMyNTYiOnsicm9sZXMiOlsidW1hX3Byb3RlY3Rpb24iXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSJ9.kBZtPPTLY1grDosKUSywxs8TIjm7ghq9GJp5KKJITBM",
    "token_type": "bearer",
    "not-before-policy": 0,
    "session_state": "f08bff0a-78d8-4127-bbbc-4dadfa54ce71",
    "scope": "email profile"
}

(2)使用工具生成公钥私钥
https://github.com/hkj123/jwk-keygen.git

curl -s -L https://github.com/openstandia/jwk-keygen/releases/download/v0.1/jwk-keygen-v0.1-linux-amd64.tar.gz | tar zx -C .bin

mkdir -p .bin
    curl -s -L https://github.com/openstandia/jwk-keygen/releases/download/v0.1/jwk-keygen-v0.1-linux-amd64.tar.gz | tar zx -C .bin
    PATH=$PATH:.bin
    
jwk-keygen --use=sig --format --jwks --pem --pem-body --alg=PS256 --kid=client1-PS256
jwk-keygen --use=sig --format --jwks --pem --pem-body --alg=PS256 --kid=client2-PS256

执行完毕会生成
在这里插入图片描述
在这里插入图片描述
导入client 私钥
在这里插入图片描述
获取keycloak公钥

curl --location --request GET 'http://localhost:8080/auth/realms/openbanking/protocol/openid-connect/certs'
  1. "client_secret_jwt"获取 id_token
    相关依赖
<dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.60</version>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.14</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-text</artifactId>
            <version>1.8</version>
        </dependency>

跳转路径生成
在这里插入图片描述

public static void main(String[] args) throws Exception{
        Provider bc = BouncyCastleProviderSingleton.getInstance();
        Security.addProvider(bc);
        String pdpUrl = "https://qms-obp-pdp-test.qloudobp.service.sd";
        String realmName = "openbanking";
        String client_id = "client1-mtls-RS256-RS256";
        String redirect_uri = "http://192.168.11.253:8888/v3/hello";
        String scope = "openid%20accounts";
        String state = "WBMDzUQtKO";
        String nonce = "axo5pyKHfk";
        String response_type = "code id_token";

        // https://tools.ietf.org/html/rfc7636#section-4.1
        char [][] pairs = {
                {'A','Z'},
                {'a','z'},
                {'0','9'},
                {'-','-'},
                {'.','.'},
                {'_','_'},
                {'~','~'},
        };
        final SecureRandom rand = new SecureRandom();
        RandomStringGenerator generator = new RandomStringGenerator.Builder()
                .usingRandom(rand::nextInt)
                .withinRange(pairs).build();
        // test maximum permitted length
        String code_verifier = generator.generate(128);

        byte[] bytes = code_verifier.getBytes(StandardCharsets.US_ASCII);
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(bytes, 0, bytes.length);
        byte[] digest = md.digest();
        String code_challenge = org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(digest);
        String code_challenge_method = "S256";
        StringBuffer bufferAud = new StringBuffer();
        bufferAud.append(pdpUrl);
        bufferAud.append("/auth/realms/");
        bufferAud.append(realmName);
        bufferAud.append("/protocol/openid-connect/auth");
        bufferAud.append("?client_id="+client_id);
        bufferAud.append("&redirect_uri="+redirect_uri);
        bufferAud.append("&scope="+scope);
        bufferAud.append("&state="+state);
        bufferAud.append("&nonce="+nonce);
        bufferAud.append("&response_type="+response_type);
        bufferAud.append("&code_challenge="+code_challenge);
        bufferAud.append("&code_challenge_method="+code_challenge_method);
        String path = bufferAud.toString();
        System.out.println(path);
    }
https://qms-obp-pdp-test.qloudobp.service.sd/auth/realms/openbanking/protocol/openid-connect/auth?client_id=client1-mtls-RS256-RS256&redirect_uri=http://192.168.11.253:8888/v3/hello&scope=openid%20accounts&state=WBMDzUQtKO&nonce=axo5pyKHfk&response_type=code

返回值:
在这里插入图片描述
解析后的参数
在这里插入图片描述

  • 14
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值