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

ea1d880ef5a03bcdd3f4697293fc4104.png

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

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

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

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

详细性能瓶颈分析,请参考上篇文章《扩展jwt解决oauth2 性能瓶颈》

本文是针对传统使用UUID token 的情况进行扩展,提高系统的吞吐率,解决性能瓶颈的问题

默认check-token 解析逻辑

RemoteTokenServices 入口

@Override

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

MultiValueMap formData = new LinkedMultiValueMap();

formData.add(tokenName, accessToken);

HttpHeaders headers = new HttpHeaders();

headers.set("Authorization", getAuthorizationHeader(clientId, clientSecret));

// 调用认证服务器的check-token 接口检查token

Map map = postForMap(checkTokenEndpointUrl, formData, headers);

return tokenConverter.extractAuthentication(map);

}

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

DefaultAccessTokenConverter

public OAuth2Authentication extractAuthentication(Map map) {

Map parameters = new HashMap();

Set scope = extractScope(map);

// 主要是 用户的信息的抽取

Authentication user = userTokenConverter.extractAuthentication(map);

// 一些oauth2 信息的填充

OAuth2Request request = new OAuth2Request(parameters, clientId, authorities, true, scope, resourceIds, null, null,

null);

return new OAuth2Authentication(request, user);

}

组装当前用户信息

DefaultUserAuthenticationConverter

public Authentication extractAuthentication(Map map) {

if (map.containsKey(USERNAME)) {

Object principal = map.get(USERNAME);

Collection extends GrantedAuthority> authorities = getAuthorities(map);

if (userDetailsService != null) {

UserDetails user = userDetailsService.loadUserByUsername((String) map.get(USERNAME));

authorities = user.getAuthorities();

principal = user;

}

return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);

}

return null;

}

问题分析

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

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

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

造成问题现象

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

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

解决问题

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

/**

* @author lengleng

* @date 2019-03-07

*

* 根据checktoken 的结果转化用户信息

*/

public class PigxUserAuthenticationConverter implements UserAuthenticationConverter {

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

// map 是check-token 返回的全部信息

@Override

public Authentication extractAuthentication(Map map) {

if (map.containsKey(USERNAME)) {

Collection extends GrantedAuthority> authorities = getAuthorities(map);

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

Integer id = (Integer) map.get(SecurityConstants.DETAILS_USER_ID);

Integer deptId = (Integer) map.get(SecurityConstants.DETAILS_DEPT_ID);

Integer tenantId = (Integer) map.get(SecurityConstants.DETAILS_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;

}

}

给remoteTokenServices 注入这个实现

public class PigxResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter {

@Override

public void configure(ResourceServerSecurityConfigurer resources) {

DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();

UserAuthenticationConverter userTokenConverter = new PigxUserAuthenticationConverter();

accessTokenConverter.setUserTokenConverter(userTokenConverter);

remoteTokenServices.setRestTemplate(lbRestTemplate);

remoteTokenServices.setAccessTokenConverter(accessTokenConverter);

resources.

.tokenServices(remoteTokenServices);

}

}

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

60dcbbbdceff3d842d32489974ce5d44.png

关注我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值