认证和授权系列主题: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

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

CentOS7安装配置mysql5.7 tar免安装版

一、CentOS7.4系统自带mariadb # 查看系统自带的Mariadb[root@localhost~]# rpm -qa|grep mariadbmariadb-libs-5.5.44-2.el7.centos.x86_64# 卸载系统自带的Mariadb[root@localhost ~]# rpm -e --nodeps mariadb-libs-5.5.44-2.el7

hadoop开启回收站配置

开启回收站功能,可以将删除的文件在不超时的情况下,恢复原数据,起到防止误删除、备份等作用。 开启回收站功能参数说明 (1)默认值fs.trash.interval = 0,0表示禁用回收站;其他值表示设置文件的存活时间。 (2)默认值fs.trash.checkpoint.interval = 0,检查回收站的间隔时间。如果该值为0,则该值设置和fs.trash.interval的参数值相等。

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

wolfSSL参数设置或配置项解释

1. wolfCrypt Only 解释:wolfCrypt是一个开源的、轻量级的、可移植的加密库,支持多种加密算法和协议。选择“wolfCrypt Only”意味着系统或应用将仅使用wolfCrypt库进行加密操作,而不依赖其他加密库。 2. DTLS Support 解释:DTLS(Datagram Transport Layer Security)是一种基于UDP的安全协议,提供类似于

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof