使用Keycloak服务器的Zuul反向代理

时间:2016-05-19 16:35:26

标签: spring-security spring-boot spring-cloud netflix-zuul keycloak

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

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

enter image description here

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

我有哪个选择?

2 个答案:

答案 0 :(得分:2)

最近我遇到了同样的问题。我通过以下方式解决了这个问题:

  1. 添加到Zuul的application.properties

    zuul.sensitive报头=饼干,设置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();
    }
    

    }

答案 1 :(得分:0)

(从评论迁移到答案)

我最终制作了一个Github project以便向钥匙斗篷团队解释我的问题,并从一位试图帮助我的开发团队成员那里请求了拉力。根据他们的建议,我得出的结论是,zuul很好地隐藏了无状态服务(仅承载者的服务),而不是用户直接与之交互的服务。这里是邮件列表中的the whole thread