我们在这里做的是 - 从访问令牌中提取额外的声明:
public Map<String, Object> getExtraInfo(OAuth2Authentication auth) { OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) auth.getDetails(); OAuth2AccessToken accessToken = tokenStore .readAccessToken(details.getTokenValue()); return accessToken.getAdditionalInformation(); }在下一节中,我们将讨论如何使用自定义AccessTokenConverter将这些额外信息添加到我们的身份验证详细信息中
6.1。自定义AccessTokenConverter让我们创建CustomAccessTokenConverter并使用访问令牌声明设置身份验证详细信息:
@Component public class CustomAccessTokenConverter extends DefaultAccessTokenConverter { @Override public OAuth2Authentication extractAuthentication(Map<String, ?> claims) { OAuth2Authentication authentication = super.extractAuthentication(claims); authentication.setDetails(claims); return authentication; } }注意:DefaultAccessTokenConverter用于将身份验证详细信息设置为Null。
6.2。配置JwtTokenStore接下来,我们将配置我们的JwtTokenStore以使用我们的CustomAccessTokenConverter:
@Configuration @EnableResourceServer public class OAuth2ResourceServerConfigJwt extends ResourceServerConfigurerAdapter { @Autowired private CustomAccessTokenConverter customAccessTokenConverter; @Bean public TokenStore tokenStore() { return new JwtTokenStore(accessTokenConverter()); } @Bean public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setAccessTokenConverter(customAccessTokenConverter); } // ... } 6.3。身份验证对象中提供的额外声明既然Authorization Server在令牌中添加了一些额外的声明,我们现在可以直接在Authentication对象中在Resource Server端访问:
public Map<String, Object> getExtraInfo(Authentication auth) { OAuth2AuthenticationDetails oauthDetails = (OAuth2AuthenticationDetails) auth.getDetails(); return (Map<String, Object>) oauthDetails .getDecodedDetails(); } 6.4。验证测试让我们确保我们的Authentication对象包含额外信息:
@RunWith(SpringRunner.class) @SpringBootTest( classes = ResourceServerApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) public class AuthenticationClaimsIntegrationTest { @Autowired private JwtTokenStore tokenStore; @Test public void whenTokenDoesNotContainIssuer_thenSuccess() { String tokenValue = obtainAccessToken("fooClientIdPassword", "john", "123"); OAuth2Authentication auth = tokenStore.readAuthentication(tokenValue); Map<String, Object> details = (Map<String, Object>) auth.getDetails(); assertTrue(details.containsKey("organization")); } private String obtainAccessToken( String clientId, String username, String password) { Map<String, String> params = new HashMap<>(); params.put("grant_type", "password"); params.put("client_id", clientId); params.put("username", username); params.put("password", password); Response response = RestAssured.given() .auth().preemptive().basic(clientId, "secret") .and().with().params(params).when() .post("http://localhost:8081/spring-security-oauth-server/oauth/token"); return response.jsonPath().getString("access_token"); } }注意:我们从授权服务器获得了具有额外声明的访问令牌,然后我们从中读取了Authentication对象,其中包含详细信息对象中的额外信息“organization”。
7.非对称KeyPair在我们之前的配置中,我们使用对称密钥来签署我们的令牌:
@Bean public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setSigningKey("123"); return converter; }我们还可以使用非对称密钥(公钥和私钥)来执行签名过程。
7.1。生成JKS Java KeyStore文件让我们首先使用命令行工具keytool生成密钥 - 更具体地说是.jks文件:
keytool -genkeypair -alias mytest -keyalg RSA -keypass mypass -keystore mytest.jks -storepass mypass该命令将生成一个名为mytest.jks的文件,其中包含我们的密钥 - 公钥和私钥。
还要确保keypass和storepass是相同的。
7.2。导出公钥接下来,我们需要从生成的JKS导出我们的公钥,我们可以使用以下命令来执行此操作:
keytool -list -rfc --keystore mytest.jks | openssl x509 -inform pem -pubkey示例响应将如下所示:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgIK2Wt4x2EtDl41C7vfp OsMquZMyOyteO2RsVeMLF/hXIeYvicKr0SQzVkodHEBCMiGXQDz5prijTq3RHPy2 /5WJBCYq7yHgTLvspMy6sivXN7NdYE7I5pXo/KHk4nz+Fa6P3L8+L90E/3qwf6j3 DKWnAgJFRY8AbSYXt1d5ELiIG1/gEqzC0fZmNhhfrBtxwWXrlpUDT0Kfvf0QVmPR xxCLXT+tEe1seWGEqeOLL5vXRLqmzZcBe1RZ9kQQm43+a9Qn5icSRnDfTAesQ3Cr lAWJKl2kcWU1HwJqw+dZRSZ1X4kEXNMyzPdPBbGmU6MHdhpywI7SKZT7mX4BDnUK eQIDAQAB -----END PUBLIC KEY----- -----BEGIN CERTIFICATE----- MIIDCzCCAfOgAwIBAgIEGtZIUzANBgkqhkiG9w0BAQsFADA2MQswCQYDVQQGEwJ1 czELMAkGA1UECBMCY2ExCzAJBgNVBAcTAmxhMQ0wCwYDVQQDEwR0ZXN0MB4XDTE2 MDMxNTA4MTAzMFoXDTE2MDYxMzA4MTAzMFowNjELMAkGA1UEBhMCdXMxCzAJBgNV BAgTAmNhMQswCQYDVQQHEwJsYTENMAsGA1UEAxMEdGVzdDCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAICCtlreMdhLQ5eNQu736TrDKrmTMjsrXjtkbFXj Cxf4VyHmL4nCq9EkM1ZKHRxAQjIhl0A8+aa4o06t0Rz8tv+ViQQmKu8h4Ey77KTM urIr1zezXWBOyOaV6Pyh5OJ8/hWuj9y/Pi/dBP96sH+o9wylpwICRUWPAG0mF7dX eRC4iBtf4BKswtH2ZjYYX6wbccFl65aVA09Cn739EFZj0ccQi10/rRHtbHlhhKnj iy+b10S6ps2XAXtUWfZEEJuN/mvUJ+YnEkZw30wHrENwq5QFiSpdpHFlNR8CasPn WUUmdV+JBFzTMsz3TwWxplOjB3YacsCO0imU+5l+AQ51CnkCAwEAAaMhMB8wHQYD VR0OBBYEFOGefUBGquEX9Ujak34PyRskHk+WMA0GCSqGSIb3DQEBCwUAA4IBAQB3 1eLfNeq45yO1cXNl0C1IQLknP2WXg89AHEbKkUOA1ZKTOizNYJIHW5MYJU/zScu0 yBobhTDe5hDTsATMa9sN5CPOaLJwzpWV/ZC6WyhAWTfljzZC6d2rL3QYrSIRxmsp /J1Vq9WkesQdShnEGy7GgRgJn4A8CKecHSzqyzXulQ7Zah6GoEUD+vjb+BheP4aN hiYY1OuXD+HsdKeQqS+7eM5U7WW6dz2Q8mtFJ5qAxjY75T0pPrHwZMlJUhUZ+Q2V FfweJEaoNB9w9McPe1cAiE+oeejZ0jq0el3/dJsx3rlVqZN+lMhRJJeVHFyeb3XF lLFCUGhA7hxn2xf3x1JW -----END CERTIFICATE-----