Zuul 反向代理与 Keycloak 服务器

Zuul reverse proxy with Keycloak server

我正在使用 Zuul 反向代理实用程序配置 Spring 云 (Angel.SR6) 应用程序,以隐藏内部服务端口。我的 zuul(边缘)服务在 8765 端口发布,我的组织服务在 8083 端口。当我在没有安全保护的情况下访问应用程序时,一切都很顺利,http://localhost:8765/organization/organizations returns JSON 所有组织。

但是,现在我想集成一个 Keycloak SSO (OAuth2) 服务器用于授权目的。我在我的组织服务中添加了 Spring Security adapter 并将其配置为在 http://localhost:8080/auth 中进行身份验证。一切顺利,除了 zuul 执行重定向而不是代理。因此,当身份验证成功时,我将被重定向到 http://localhost:8083/organizations 而不是 http://localhost:8765/organization/organizations。这是我的浏览器请求:

这是因为 keycloak 适配器在 http://localhost:8083/sso/login 中创建了一个令牌验证端点,它从该端点执行到授权服务器的重定向以验证令牌。当授权服务器确认它时,重定向将发送到组织服务,路径为 /organization,因此正在加载的结尾 url 是 http://localhost:8083/organizations。但我希望加载第一个请求的 url 。

我有什么选择?

最近我遇到了同样的问题。我已经解决了:

  1. 添加到 Zuul 中的 application.properties

    zuul.sensitive-headers=Cookie,Set-Cookie

  2. 在Zuul中引入KeycloakFilterRoute

    class KeycloakFilterRoute extends ZuulFilter {
    
    private static final String AUTHORIZATION_HEADER = "authorization";
    
    @Override
    public String filterType() {
        return "route";
    }
    
    @Override
    public int filterOrder() {
        return 0;
    }
    
    @Override
    public boolean shouldFilter() {
        return true;
    }
    
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        if (ctx.getRequest().getHeader(AUTHORIZATION_HEADER) == null) {
            addKeycloakTokenToHeader(ctx);
        }
        return null;
    }
    
    private void addKeycloakTokenToHeader(RequestContext ctx) {
        RefreshableKeycloakSecurityContext securityContext = getRefreshableKeycloakSecurityContext(ctx);
        if (securityContext != null) {
            ctx.addZuulRequestHeader(AUTHORIZATION_HEADER, buildBearerToken(securityContext));
        }
    }
    
    private RefreshableKeycloakSecurityContext getRefreshableKeycloakSecurityContext(RequestContext ctx) {
        if (ctx.getRequest().getUserPrincipal() instanceof KeycloakAuthenticationToken) {
            KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) ctx.getRequest().getUserPrincipal();
            return (RefreshableKeycloakSecurityContext) token.getCredentials();
        }
        return null;
    }
    
    private String buildBearerToken(RefreshableKeycloakSecurityContext securityContext) {
        return "Bearer " + securityContext.getTokenString();
    }
    

    }

(从评论迁移到答案)

我最终在邮件列表中创建了 Github project in order to explain my problem to the keycloak team, and got a pull request from one of the development team members trying to help me out. Following their recommendations, I came into the conclusion that zuul is good to hide stateless services (bearer only ones), but not the ones that user directly interacts with. Here it is the whole thread