认证和授权系列主题:keycloak界面配置及认证流程详解

2024-06-11 06:08

本文主要是介绍认证和授权系列主题:keycloak界面配置及认证流程详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文转自:彻骨寒风

keycloak设置master登录用户

keycloak 管理界面

keycloak 获取用户token 

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

  • 添加域的用户

  • 设置密码

  •  创建client(普通用户登录 设置public)

  • 查看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"
}
  • 获取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"
}
  • 用户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'

  • confidential client 设置 

public confidential 区别:
public 就是简单的账号密码登录
confidential 需要算法支持
从配置中可以看到支持5种: 

     "private_key_jwt","client_secret_basic","client_secret_post","tls_client_auth","client_secret_jwt"
  • 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参数的修改

  • 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'
  •  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());

  • 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 useJWK 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 .binmkdir -p .bincurl -s -L https://github.com/openstandia/jwk-keygen/releases/download/v0.1/jwk-keygen-v0.1-linux-amd64.tar.gz | tar zx -C .binPATH=$PATH:.binjwk-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'

"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.1char [][] 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 lengthString 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

返回值:

解析后的参数

 

 

这篇关于认证和授权系列主题:keycloak界面配置及认证流程详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1050372

相关文章

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

一文详解如何在Python中从字符串中提取部分内容

《一文详解如何在Python中从字符串中提取部分内容》:本文主要介绍如何在Python中从字符串中提取部分内容的相关资料,包括使用正则表达式、Pyparsing库、AST(抽象语法树)、字符串操作... 目录前言解决方案方法一:使用正则表达式方法二:使用 Pyparsing方法三:使用 AST方法四:使用字

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

如何在Mac上安装并配置JDK环境变量详细步骤

《如何在Mac上安装并配置JDK环境变量详细步骤》:本文主要介绍如何在Mac上安装并配置JDK环境变量详细步骤,包括下载JDK、安装JDK、配置环境变量、验证JDK配置以及可选地设置PowerSh... 目录步骤 1:下载JDK步骤 2:安装JDK步骤 3:配置环境变量1. 编辑~/.zshrc(对于zsh

python logging模块详解及其日志定时清理方式

《pythonlogging模块详解及其日志定时清理方式》:本文主要介绍pythonlogging模块详解及其日志定时清理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录python logging模块及日志定时清理1.创建logger对象2.logging.basicCo

售价599元起! 华为路由器X1/Pro发布 配置与区别一览

《售价599元起!华为路由器X1/Pro发布配置与区别一览》华为路由器X1/Pro发布,有朋友留言问华为路由X1和X1Pro怎么选择,关于这个问题,本期图文将对这二款路由器做了期参数对比,大家看... 华为路由 X1 系列已经正式发布并开启预售,将在 4 月 25 日 10:08 正式开售,两款产品分别为华

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/