如上步骤在实际使用,会形成认证中心的负载压力过大,成为形成整个系统瓶颈的关键点。 git
@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 的最大缺点是,因为服务器不保存 session 状态,所以没法在使用过程当中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期以前就会始终有效,除非服务器部署额外的逻辑。spring
去认证服务器校验的过程就是 经过tokenstore 来控制jwt 安全性的一个方法,去掉Check-token 意味着 jwt token 安全性不可保证安全
JWT 自己包含了认证信息,一旦泄露,任何人均可以得到该令牌的全部权限。为了减小盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。服务器
为了减小盗用,JWT 不该该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。网络