在开发中各种需求都能遇见,我司的系统权限控制的比较糙(只有菜单权限没有接口权限,潜在的风险,随时都能出现越权的查询),这块咱也是接过来的锅,只能在上面堆。。
只要在auth服务获取token后就可以访问系统中所有的资源,现在我司让将token隔离开,就是PC的token只能访问PC的资源,APP只能访问APP的资源。之前可虑过在网关上显示限制访问的权限,但是感觉不够优雅,所以尝试扩展JwtAccessTokenConverter来解决上面的业务需求。这种扩展只能用于在网关拦截器中做权限的系统,这样的话子系统是不存在携带token远程调用的。我司的系统是每个子系统在做权限验证所以不适合这种扩展。
1.用于存储signingKey
public class ClientKeyStore implements Serializable {
private static final Map<String, String> clientKeys = new HashMap<>();
static {
clientKeys.put("client", "Anh4V1dDRCM0QUQ2ZiZlcXo=");
clientKeys.put("mobile", "YXBwLWhlYWx0aC0yMDI0LTA2MTg=");
// 添加其他客户端和它们的密钥
}
public static String getKey(String clientId) {
return clientKeys.get(clientId);
}
}
2.用于 signingKey 的适配
public class CustomJwtAccessTokenConverter extends JwtAccessTokenConverter {
@Override
protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
String clientId = authentication.getOAuth2Request().getClientId();
String signingKey = ClientKeyStore.getKey(clientId);
if (signingKey != null) {
this.setSigningKey(signingKey);
}
return super.encode(accessToken, authentication);
}
@Override
protected Map<String, Object> decode(String token) {
String clientId = extractClientId(token);
String signingKey = ClientKeyStore.getKey(clientId);
if (signingKey != null) {
this.setSigningKey(signingKey);
}
return super.decode(token);
}
private String extractClientId(String token) {
// 从 token 中提取 clientId 的逻辑
// 这可以根据你的 token 的具体结构来实现
Map<String, Object> decode = super.decode(token);
return (String) decode.get("client_id");
}
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
CustomJwtAccessTokenConverter converter = new CustomJwtAccessTokenConverter();
return converter;
}