资讯专栏INFORMATION COLUMN

扩展资源服务器解决oauth2 性能瓶颈

DevYK / 1115人阅读

摘要:用户携带请求资源服务器资源服务器拦截器携带去认证服务器调用对合法性校验资源服务器拿到,默认只会含有用户名信息通过用户名调用查询用户全部信息详细性能瓶颈分析,请参考上篇文章扩展解决性能瓶颈本文是针对传统使用的情况进行扩展,提高系统的吞吐率,解

用户携带token 请求资源服务器

资源服务器拦截器 携带token 去认证服务器 调用tokenstore 对token 合法性校验

资源服务器拿到token,默认只会含有用户名信息

通过用户名调用userdetailsservice.loadbyusername 查询用户全部信息

详细性能瓶颈分析,请参考上篇文章《扩展jwt解决oauth2 性能瓶颈》
本文是针对传统使用UUID token 的情况进行扩展,提高系统的吞吐率,解决性能瓶颈的问题

默认check-token 解析逻辑

RemoteTokenServices 入口

</>复制代码

  1. @Override
  2. public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException {
  3. MultiValueMap formData = new LinkedMultiValueMap();
  4. formData.add(tokenName, accessToken);
  5. HttpHeaders headers = new HttpHeaders();
  6. headers.set("Authorization", getAuthorizationHeader(clientId, clientSecret));
  7. // 调用认证服务器的check-token 接口检查token
  8. Map map = postForMap(checkTokenEndpointUrl, formData, headers);
  9. return tokenConverter.extractAuthentication(map);
  10. }

解析认证服务器返回的信息

DefaultAccessTokenConverter

</>复制代码

  1. public OAuth2Authentication extractAuthentication(Map map) {
  2. Map parameters = new HashMap();
  3. Set scope = extractScope(map);
  4. // 主要是 用户的信息的抽取
  5. Authentication user = userTokenConverter.extractAuthentication(map);
  6. // 一些oauth2 信息的填充
  7. OAuth2Request request = new OAuth2Request(parameters, clientId, authorities, true, scope, resourceIds, null, null,
  8. null);
  9. return new OAuth2Authentication(request, user);
  10. }

组装当前用户信息

DefaultUserAuthenticationConverter

</>复制代码

  1. public Authentication extractAuthentication(Map map) {
  2. if (map.containsKey(USERNAME)) {
  3. Object principal = map.get(USERNAME);
  4. Collection authorities = getAuthorities(map);
  5. if (userDetailsService != null) {
  6. UserDetails user = userDetailsService.loadUserByUsername((String) map.get(USERNAME));
  7. authorities = user.getAuthorities();
  8. principal = user;
  9. }
  10. return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);
  11. }
  12. return null;
  13. }
问题分析

认证服务器check-token 返回的全部信息

资源服务器在根据返回信息组装用户信息的时候,只是用了username

如果设置了 userDetailsService 的实现则去调用 loadUserByUsername 再去查询一次用户信息

造成问题现象

如果设置了userDetailsService 即可在spring security 上下文获取用户的全部信息,不设置则只能得到用户名。

增加了一次查询逻辑,对性能产生不必要的影响

解决问题

扩展UserAuthenticationConverter 的解析过程,把认证服务器返回的信息全部组装到spring security的上下文对象中

</>复制代码

  1. /**
  2. * @author lengleng
  3. * @date 2019-03-07
  4. *

  5. * 根据checktoken 的结果转化用户信息
  6. */
  7. public class PigxUserAuthenticationConverter implements UserAuthenticationConverter {
  8. private static final String N_A = "N/A";
  9. // map 是check-token 返回的全部信息
  10. @Override
  11. public Authentication extractAuthentication(Map map) {
  12. if (map.containsKey(USERNAME)) {
  13. Collection authorities = getAuthorities(map);
  14. String username = (String) map.get(USERNAME);
  15. Integer id = (Integer) map.get(SecurityConstants.DETAILS_USER_ID);
  16. Integer deptId = (Integer) map.get(SecurityConstants.DETAILS_DEPT_ID);
  17. Integer tenantId = (Integer) map.get(SecurityConstants.DETAILS_TENANT_ID);
  18. PigxUser user = new PigxUser(id, deptId, tenantId, username, N_A, true
  19. , true, true, true, authorities);
  20. return new UsernamePasswordAuthenticationToken(user, N_A, authorities);
  21. }
  22. return null;
  23. }
  24. }

给remoteTokenServices 注入这个实现

</>复制代码

  1. public class PigxResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter {
  2. @Override
  3. public void configure(ResourceServerSecurityConfigurer resources) {
  4. DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
  5. UserAuthenticationConverter userTokenConverter = new PigxUserAuthenticationConverter();
  6. accessTokenConverter.setUserTokenConverter(userTokenConverter);
  7. remoteTokenServices.setRestTemplate(lbRestTemplate);
  8. remoteTokenServices.setAccessTokenConverter(accessTokenConverter);
  9. resources.
  10. .tokenServices(remoteTokenServices);
  11. }
  12. }

完成扩展,再来看文章开头的流程图就变成了如下

关注我

个人项目 基于Spring Cloud、OAuth2.0开发基于Vue前后分离的开发平台

QQ: 2270033969 一起来聊聊你们是咋用 spring cloud 的吧。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77465.html

相关文章

  • 扩展资源务器解决oauth2 性能瓶颈

    摘要:用户携带请求资源服务器资源服务器拦截器携带去认证服务器调用对合法性校验资源服务器拿到,默认只会含有用户名信息通过用户名调用查询用户全部信息详细性能瓶颈分析,请参考上篇文章扩展解决性能瓶颈本文是针对传统使用的情况进行扩展,提高系统的吞吐率,解 showImg(https://segmentfault.com/img/remote/1460000018549849?w=519&h=402)...

    Rocture 评论0 收藏0
  • 服务网关方案调研

    摘要:综述经调研,使用解决方案的占多数,已经能满足绝大多数公司需求。但除了一些超级公司外,比如阿里,京东,他们是自己撸的一套网关。 综述 经调研,使用Spring Cloud Zuul解决方案的占多数,已经能满足绝大多数公司需求。但除了一些超级公司外,比如阿里,京东,他们是自己撸的一套网关。此外,点评直接采用的nginx负载均衡前置网关,而没用第七层网关,原因据说是七层网关会影响性能,但由于...

    Y3G 评论0 收藏0
  • 如何在微服务架构中对资源(前端页面+后端接口)进行权限控制

    如何对资源(前端页面+后端接口)进行权限控制 在微服务架构中,请求的拦截在gateway中完成,而权限的查询是在uaa中完成,在gateway和uaa集成部署的情况下实现较为简单,如果两者分离实现起来就会比较麻烦,一种方案是在gateway的资源filter中内部调用uaa的权限查询模块,该方案是可行的,但是存在两个弊端: 响应延时:每个资源的请求都会附带一次uaa内部调用,加重uaa服务的负担...

    Nosee 评论0 收藏0
  • SpringCloud打造微服务平台--概览

    摘要:授权框架使第三方应用程序来获取对服务的有限访问机会。无论是通过编排资源所有者和服务之间的交互批准的资源所有者,或通过允许第三方应用程序来获取自己的访问权限。 SpringCloud打造微服务平台--概览 简述 SpringCloud是什么 Spring Boot和SpringCloud是什么关系 Spring Boot是Spring的一套快速WEB开发的脚手架,可建立独立的Sprin...

    siberiawolf 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<