本文主要是介绍认证和授权系列主题: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界面配置及认证流程详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!