伍佰目录 短网址
  当前位置:海洋目录网 » 站长资讯 » 站长资讯 » 文章详细 订阅RssFeed

扩展 jwt 解决 oauth2 性能瓶颈

来源:本站原创 浏览:126次 时间:2022-10-14
oauth2 性能瓶颈资源服务器的请求都会被拦截 到认证服务器校验合法性 (如下图)
  • 用户携带token 请求资源服务器

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

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

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

  • 如上步骤在实际使用,会造成认证中心的负载压力过大,成为造成整个系统瓶颈的关键点


check-token 过程中涉及的源码
  • 更为详细的源码讲解可以参考我上篇文章《Spring Cloud OAuth2 资源服务器CheckToken 源码解析》

  • check-token 涉及到的核心类

扩展jwt 生成携带用户详细信息
  • 为什么使用jwt 替代默认的UUID token ?
    通过jwt 访问资源服务器后,不再使用check-token 过程,通过对jwt 的解析即可实现身份验证,登录信息的传递。减少网络开销,提高整体微服务集群的性能

  • spring security oauth 默认的jwttoken 只含有username,通过扩展TokenEnhancer,实现关键字段的注入到 JWT 中,方便资源服务器使用

  1.    @Bean

  2.    public TokenEnhancer tokenEnhancer() {

  3.        return (accessToken, authentication) -> {

  4.            if (SecurityConstants.CLIENT_CREDENTIALS

  5.                    .equals(authentication.getOAuth2Request().getGrantType())) {

  6.                return accessToken;

  7.            }


  8.            final Map<String, Object> additionalInfo = new HashMap<>(8);

  9.            PigxUser pigxUser = (PigxUser) authentication.getUserAuthentication().getPrincipal();

  10.            additionalInfo.put("user_id", pigxUser.getId());

  11.            additionalInfo.put("username", pigxUser.getUsername());

  12.            additionalInfo.put("dept_id", pigxUser.getDeptId());

  13.            additionalInfo.put("tenant_id", pigxUser.getTenantId());

  14.            additionalInfo.put("license", SecurityConstants.PIGX_LICENSE);

  15.            ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);

  16.            return accessToken;

  17.        };

  18.    }

  • 生成的token 如下,含有关键的字段

重写默认的资源服务器处理行为
  • 不再使用RemoteTokenServices 去掉用认证中心 CheckToken,自定义客户端TokenService

  1. @Slf4j

  2. public class PigxCustomTokenServices implements ResourceServerTokenServices {

  3.    @Setter

  4.    private TokenStore tokenStore;


  5.    @Setter

  6.    private DefaultAccessTokenConverter defaultAccessTokenConverter;


  7.    @Setter

  8.    private JwtAccessTokenConverter jwtAccessTokenConverter;


  9.    @Override

  10.    public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException {

  11.        OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(accessToken);

  12.        UserAuthenticationConverter userTokenConverter = new PigxUserAuthenticationConverter();

  13.        defaultAccessTokenConverter.setUserTokenConverter(userTokenConverter);

  14.        Map<String, ?> map = jwtAccessTokenConverter.convertAccessToken(readAccessToken(accessToken), oAuth2Authentication);

  15.        return defaultAccessTokenConverter.extractAuthentication(map);

  16.    }



  17.    @Override

  18.    public OAuth2AccessToken readAccessToken(String accessToken) {

  19.        return tokenStore.readAccessToken(accessToken);

  20.    }

  21. }

  • 解析jwt 组装成Authentication

  1. /**

  2. * @author lengleng

  3. * @date 2019-03-17

  4. * <p>

  5. * jwt 转化用户信息

  6. */

  7. public class PigxUserAuthenticationConverter implements UserAuthenticationConverter {

  8.    private static final String USER_ID = "user_id";

  9.    private static final String DEPT_ID = "dept_id";

  10.    private static final String TENANT_ID = "tenant_id";

  11.    private static final String N_A = "N/A";


  12.    @Override

  13.    public Authentication extractAuthentication(Map<String, ?> map) {

  14.        if (map.containsKey(USERNAME)) {

  15.            Collection<? extends GrantedAuthority> authorities = getAuthorities(map);


  16.            String username = (String) map.get(USERNAME);

  17.            Integer id = (Integer) map.get(USER_ID);

  18.            Integer deptId = (Integer) map.get(DEPT_ID);

  19.            Integer tenantId = (Integer) map.get(TENANT_ID);

  20.            PigxUser user = new PigxUser(id, deptId, tenantId, username, N_A, true

  21.                    , true, true, true, authorities);

  22.            return new UsernamePasswordAuthenticationToken(user, N_A, authorities);

  23.        }

  24.        return null;

  25.    }


  26.    private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {

  27.        Object authorities = map.get(AUTHORITIES);

  28.        if (authorities instanceof String) {

  29.            return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);

  30.        }

  31.        if (authorities instanceof Collection) {

  32.            return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils

  33.                    .collectionToCommaDelimitedString((Collection<?>) authorities));

  34.        }

  35.        throw new IllegalArgumentException("Authorities must be either a String or a Collection");

  36.    }

  37. }

  • 资源服务器配置中注入以上配置即可

  1. @Slf4j

  2. public class PigxResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter {

  3.    @Override

  4.    public void configure(ResourceServerSecurityConfigurer resources) {

  5.        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();

  6.        UserAuthenticationConverter userTokenConverter = new PigxUserAuthenticationConverter();

  7.        accessTokenConverter.setUserTokenConverter(userTokenConverter);


  8.        PigxCustomTokenServices tokenServices = new PigxCustomTokenServices();


  9.        // 这里的签名key 保持和认证中心一致

  10.        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();

  11.        converter.setSigningKey("123");

  12.        converter.setVerifier(new MacSigner("123"));

  13.        JwtTokenStore jwtTokenStore = new JwtTokenStore(converter);

  14.        tokenServices.setTokenStore(jwtTokenStore);

  15.        tokenServices.setJwtAccessTokenConverter(converter);

  16.        tokenServices.setDefaultAccessTokenConverter(accessTokenConverter);


  17.        resources

  18.                .authenticationEntryPoint(resourceAuthExceptionEntryPoint)

  19.                .tokenServices(tokenServices);

  20.    }

  21. }

使用JWT 扩展后带来的问题
  • JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

  • 去认证服务器校验的过程就是 通过tokenstore 来控制jwt 安全性的一个方法,去掉Check-token 意味着 jwt token 安全性不可保证

  • JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

  • 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。


  推荐站点

  • At-lib分类目录At-lib分类目录

    At-lib网站分类目录汇集全国所有高质量网站,是中国权威的中文网站分类目录,给站长提供免费网址目录提交收录和推荐最新最全的优秀网站大全是名站导航之家

    www.at-lib.cn
  • 中国链接目录中国链接目录

    中国链接目录简称链接目录,是收录优秀网站和淘宝网店的网站分类目录,为您提供优质的网址导航服务,也是网店进行收录推广,站长免费推广网站、加快百度收录、增加友情链接和网站外链的平台。

    www.cnlink.org
  • 35目录网35目录网

    35目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向35目录推荐、提交优秀网站。

    www.35mulu.com
  • 就要爱网站目录就要爱网站目录

    就要爱网站目录,按主题和类别列出网站。所有提交的网站都经过人工审查,确保质量和无垃圾邮件的结果。

    www.912219.com
  • 伍佰目录伍佰目录

    伍佰网站目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向伍佰目录推荐、提交优秀网站。

    www.wbwb.net