Spring-BootSpringBoot极简教程 · Spring Boot

扩展jwt解决oauth2 性能瓶颈

2019-03-18  本文已影响8人  冷冷zz

oauth2 性能瓶颈

资源服务器的请求都会被拦截 到认证服务器校验合法性 (如下图)

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

image

check-token 过程中涉及的源码

扩展jwt 生成携带用户详细信息

    @Bean
    public TokenEnhancer tokenEnhancer() {
        return (accessToken, authentication) -> {
            if (SecurityConstants.CLIENT_CREDENTIALS
                    .equals(authentication.getOAuth2Request().getGrantType())) {
                return accessToken;
            }

            final Map<String, Object> additionalInfo = new HashMap<>(8);
            PigxUser pigxUser = (PigxUser) authentication.getUserAuthentication().getPrincipal();
            additionalInfo.put("user_id", pigxUser.getId());
            additionalInfo.put("username", pigxUser.getUsername());
            additionalInfo.put("dept_id", pigxUser.getDeptId());
            additionalInfo.put("tenant_id", pigxUser.getTenantId());
            additionalInfo.put("license", SecurityConstants.PIGX_LICENSE);
            ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
            return accessToken;
        };
    }

重写默认的资源服务器处理行为

@Slf4j
public class PigxCustomTokenServices implements ResourceServerTokenServices {
    @Setter
    private TokenStore tokenStore;

    @Setter
    private DefaultAccessTokenConverter defaultAccessTokenConverter;

    @Setter
    private JwtAccessTokenConverter jwtAccessTokenConverter;
    
    @Override
    public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException, InvalidTokenException {
        OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(accessToken);
        UserAuthenticationConverter userTokenConverter = new PigxUserAuthenticationConverter();
        defaultAccessTokenConverter.setUserTokenConverter(userTokenConverter);
        Map<String, ?> map = jwtAccessTokenConverter.convertAccessToken(readAccessToken(accessToken), oAuth2Authentication);
        return defaultAccessTokenConverter.extractAuthentication(map);
    }


    @Override
    public OAuth2AccessToken readAccessToken(String accessToken) {
        return tokenStore.readAccessToken(accessToken);
    }
}
/**
 * @author lengleng
 * @date 2019-03-17
 * <p>
 * jwt 转化用户信息
 */
public class PigxUserAuthenticationConverter implements UserAuthenticationConverter {
    private static final String USER_ID = "user_id";
    private static final String DEPT_ID = "dept_id";
    private static final String TENANT_ID = "tenant_id";
    private static final String N_A = "N/A";
    
    @Override
    public Authentication extractAuthentication(Map<String, ?> map) {
        if (map.containsKey(USERNAME)) {
            Collection<? extends GrantedAuthority> authorities = getAuthorities(map);

            String username = (String) map.get(USERNAME);
            Integer id = (Integer) map.get(USER_ID);
            Integer deptId = (Integer) map.get(DEPT_ID);
            Integer tenantId = (Integer) map.get(TENANT_ID);
            PigxUser user = new PigxUser(id, deptId, tenantId, username, N_A, true
                    , true, true, true, authorities);
            return new UsernamePasswordAuthenticationToken(user, N_A, authorities);
        }
        return null;
    }

    private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
        Object authorities = map.get(AUTHORITIES);
        if (authorities instanceof String) {
            return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);
        }
        if (authorities instanceof Collection) {
            return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils
                    .collectionToCommaDelimitedString((Collection<?>) authorities));
        }
        throw new IllegalArgumentException("Authorities must be either a String or a Collection");
    }
}

@Slf4j
public class PigxResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        UserAuthenticationConverter userTokenConverter = new PigxUserAuthenticationConverter();
        accessTokenConverter.setUserTokenConverter(userTokenConverter);

        PigxCustomTokenServices tokenServices = new PigxCustomTokenServices();
        
        // 这里的签名key 保持和认证中心一致
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("123");
        converter.setVerifier(new MacSigner("123"));
        JwtTokenStore jwtTokenStore = new JwtTokenStore(converter);
        tokenServices.setTokenStore(jwtTokenStore);
        tokenServices.setJwtAccessTokenConverter(converter);
        tokenServices.setDefaultAccessTokenConverter(accessTokenConverter);

        resources
                .authenticationEntryPoint(resourceAuthExceptionEntryPoint)
                .tokenServices(tokenServices);
    }
}

使用JWT 扩展后带来的问题

关注我

上一篇下一篇

猜你喜欢

热点阅读