当前位置:   article > 正文

[总结]spring security oauth2认证回执源码分析_oauth2accesstokenjackson2serializer

oauth2accesstokenjackson2serializer

目录

1.回执

回执版本一(默认)

回执版本二

2.回执DefaultOAuth2AccessToken类图

3.请求/oauth/token流程

3.1.CompositeTokenGranter.grant

3.1.1根据前端传参的grantType,匹配数组tokenGranters中的对应类型

3.1.2.validateGrantType看ClientDetails是否有对应的grantType的权限

3.1.3.获取用户token

3.2.返回token

4.两个版本回执的原因

4.1.OAuth2AccessToken的序列化方式有两种

4.2.版本1回执OAuth2AccessTokenJackson2Serializer

4.3.版本2回执OAuth2AccessTokenJackson1Serializer

4.4.回执版本变化的原因

4.5.fastJSON使用默认回执数据结构


 

 

1.回执

回执版本一(默认)

  1. * {
  2. * "access_token": "eeff86b8-66d5-428c-9c2b-9d1cce4d502a",
  3. * "token_type": "bearer",
  4. * "refresh_token": "7cc00001-ba52-473f-9c49-ee63f2ca1a0c",
  5. * "expires_in": 1799,
  6. * "scope": "read write trust"
  7. * }

回执版本二

DefaultOAuth2AccessToken

  1. * {
  2. * "additionalInformation": {},
  3. * "expiration": "2020-01-13 16:52:45",
  4. * "expired": false,
  5. * "expiresIn": 1598,
  6. * "refreshToken": {
  7. * "expiration": "2020-01-13 17:22:45",
  8. * "value": "a8ddb0a0-5872-4b70-aa12-3f0a4c4e9247"
  9. * },
  10. * "scope": [
  11. * "read",
  12. * "write",
  13. * "trust"
  14. * ],
  15. * "tokenType": "bearer",
  16. * "value": "2b576b11-cad8-4756-89e6-7090023407b2"
  17. *}

2.回执DefaultOAuth2AccessToken类图

 

 

 

3.请求/oauth/token流程

3.1.CompositeTokenGranter.grant

 

3.1.1根据前端传参的grantType,匹配数组tokenGranters中的对应类型

 

 

 

granter.grant()方法如果grantType不匹配,就直接返回null。如果匹配就validateGrantType

 

3.1.2.validateGrantType看ClientDetails是否有对应的grantType的权限

 

 

这个set的值,是我们根据用户去在数据库保存的。

 

 

3.1.3.获取用户token

 

 

先从tokenStore获取有没有token,如果token存在,则校验是否过期,过期了则先清除刷新token,再清除该token。

 

有5种getAccessToken方式,我们如果用的是数据库,就是JdbcTokenStore

如果没有已经存在的token,则新建

 

 

 

新建的token类型正是DefaultOAuth2AccessToken

 

3.2.返回token

返回结果会通过通用的项目的WebMvcConfigurerAdapter进行序列化(因为实际上也是http请求的回执)

 

 

4.两个版本回执的原因

4.1.OAuth2AccessToken的序列化方式有两种

OAuth2AccessTokenJackson1Serializer

OAuth2AccessTokenJackson2Serializer

 

4.2.版本1回执OAuth2AccessTokenJackson2Serializer

 

  1. {
  2. "access_token": "2de139d5-4b8e-49d0-baf4-1f37a9b3796d",
  3. "token_type": "bearer",
  4. "refresh_token": "f35dae51-c6d3-4a10-86b7-5f417834baa4",
  5. "expires_in": 1793,
  6. "scope": "read write trust"
  7. }

 

4.3.版本2回执OAuth2AccessTokenJackson1Serializer

 

  1. {
  2. "additionalInformation": {},
  3. "expiration": "2020-01-14 11:07:49",
  4. "expired": false,
  5. "expiresIn": 1798,
  6. "refreshToken": {
  7. "expiration": "2020-01-14 11:37:49",
  8. "value": "47ad8c7b-61f9-41db-bb7c-8a020efc38a1"
  9. },
  10. "scope": [
  11. "read",
  12. "write",
  13. "trust"
  14. ],
  15. "tokenType": "bearer",
  16. "value": "6a49bff9-2f70-41cb-b83b-209294c45c0c"
  17. }

 

 

4.4.回执版本变化的原因

Spring Security Oauth2 返回非标准数据结构 OAuth2AccessToken 序列化问题_yuelangyc的专栏-CSDN博客 https://blog.csdn.net/yuelangyc/article/details/88235639

 

如文章所述,如果自定义了消息处理,覆盖了默认的消息处理器。

 

使用 fastjson 时, spring security oauth2 获取 token 格式变化 · Issue #1640 · alibaba/fastjson https://github.com/alibaba/fastjson/issues/1640

 

针对fastjson,确实存在自定义fastjson消息处理器时,出现回执版本变化。

 

4.5.fastJSON使用默认回执数据结构

参考上面的文章

 

你需要自行写个HttpMessageConverter来转换OAuth2AccessToken,fastjson本身也意识到这个问题,但是FormOAuth2AccessTokenMessageConverter这个类的writeInternal方法没有进行实现,你需要自行实现转换

  1. public class OAuth2AccessTokenMessageConverter extends AbstractHttpMessageConverter<OAuth2AccessToken> {
  2. private final FastJsonHttpMessageConverter delegateMessageConverter;
  3. public OAuth2AccessTokenMessageConverter() {
  4. super(MediaType.APPLICATION_JSON);
  5. this.delegateMessageConverter = new FastJsonHttpMessageConverter();
  6. }
  7. @Override
  8. protected boolean supports(Class<?> clazz) {
  9. return OAuth2AccessToken.class.isAssignableFrom(clazz);
  10. }
  11. @Override
  12. protected OAuth2AccessToken readInternal(Class<? extends OAuth2AccessToken> clazz, HttpInputMessage inputMessage)
  13. throws IOException, HttpMessageNotReadableException {
  14. throw new UnsupportedOperationException(
  15. "This converter is only used for converting from externally acquired form data");
  16. }
  17. @Override
  18. protected void writeInternal(OAuth2AccessToken accessToken, HttpOutputMessage outputMessage) throws IOException,
  19. HttpMessageNotWritableException {
  20. Map<String, Object> data = new HashMap<>(8);
  21. data.put(OAuth2AccessToken.ACCESS_TOKEN, accessToken.getValue());
  22. data.put(OAuth2AccessToken.TOKEN_TYPE, accessToken.getTokenType());
  23. data.put(OAuth2AccessToken.EXPIRES_IN, accessToken.getExpiresIn());
  24. data.put(OAuth2AccessToken.SCOPE, String.join(" ", accessToken.getScope()));
  25. OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
  26. if (Objects.nonNull(refreshToken)) {
  27. data.put(OAuth2AccessToken.REFRESH_TOKEN, refreshToken.getValue());
  28. }
  29. delegateMessageConverter.write(data, MediaType.APPLICATION_JSON, outputMessage);
  30. }
  31. }

注意:上面问题回答针对的只是OAuth2AccessToken,所以实际上,如果我们的项目还有其他的http请求需要处理,则需要修改上面的转换器,只处理token的回执保持兼容,其他请求的回执仍然保持原样

  1. public class OAuth2AccessTokenMessageConverter extends AbstractHttpMessageConverter<Object> { //这里替换成Object
  2. @Override
  3. protected Object readInternal(Class<? extends OAuth2AccessToken> clazz, HttpInputMessage inputMessage)
  4. throws IOException, HttpMessageNotReadableException {
  5. //需要写自己的转换规则
  6. }
  7. @Override
  8. protected void writeInternal(Object t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
  9. String jsonString = JSON.toJSONString(t);
  10. if (t instanceof DefaultOAuth2AccessToken) {
  11. DefaultOAuth2AccessToken oAuth2AccessToken = JSON.parseObject(jsonString, DefaultOAuth2AccessToken.class);
  12. Map<String, Object> data = new HashMap<>(8);
  13. data.put(OAuth2AccessToken.ACCESS_TOKEN, oAuth2AccessToken.getValue());
  14. data.put(OAuth2AccessToken.TOKEN_TYPE, oAuth2AccessToken.getTokenType());
  15. data.put(OAuth2AccessToken.EXPIRES_IN, oAuth2AccessToken.getExpiresIn());
  16. data.put(OAuth2AccessToken.SCOPE, String.join(" ", oAuth2AccessToken.getScope()));
  17. //获取refreshToken
  18. JSONObject jsonObject = JSON.parseObject(jsonString);
  19. String refreshTokenString = jsonObject.getString("refreshToken");
  20. if (Objects.nonNull(refreshTokenString)) {
  21. data.put(OAuth2AccessToken.REFRESH_TOKEN, JSONObject.parseObject(refreshTokenString).getString("value"));
  22. }
  23. jsonString = JSON.toJSONString(data);
  24. }
  25. StreamUtils.copy(jsonString, DEFAULT_CHARSET, outputMessage.getBody());
  26. }
  27. }

 

加入MessageConverters

  1. @Configuration
  2. public class Oauth2WebMvcConfigurer implements WebMvcConfigurer {
  3. @Override
  4. public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  5. converters.add(0, new OAuth2AccessTokenMessageConverter());
  6. }
  7. }

你可以参考OAuth2AccessToken这个序列化类OAuth2AccessTokenJackson2Serializer进行编写相应的代码

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/84007
推荐阅读
相关标签
  

闽ICP备14008679号