使用 nginx 代理的带有 keycloak 的 Spring Boot 仅在 redirect_uri localhost 时才有效

Posted

技术标签:

【中文标题】使用 nginx 代理的带有 keycloak 的 Spring Boot 仅在 redirect_uri localhost 时才有效【英文标题】:Spring boot with keycloak using nginx proxy only works if redirect_uri localhost 【发布时间】:2021-07-22 02:46:13 【问题描述】:

我一直在努力解决这个问题。

我有一个使用 Spring Boot 在 localhost:8082 上运行的基本 Web 应用程序,一个在 localhost:8081 上运行的 dockerized keycloak 服务器和一个在端口 80 上运行的 dockerized nginx 服务器。

当我使用 keycloak 没有 spring 安全集成时,访问安全资源的用户将被重定向到 http://keycloak-server 的 keycloak 登录页面/auth/realms/myrealm/protocol/openid-connect/auth/... 一切都很好。

当我根据this tutorial 和其他几个人将弹簧安全性添加到组合中时,突然我的应用程序尝试重定向到没有 /sso/login 端点的 http://myapp/sso/login 所以我得到一个 404。

我只能通过直接在 http://localhost:8082 访问应用程序并将客户端的 keycloak 中的 redirect_uri 设置为 http://localhost:8082/* 来将应用程序路由到正确的登录端点.

我怀疑它可能与 nginx 配置有关,但同样,在我将 spring 安全性添加到组合中之前它已经工作了,所以我摸不着头脑。这是我的 nginx.conf

worker_processes 2;

events 
    worker_connections 1024;


http 

    proxy_set_header    Host               $host;
    proxy_set_header    X-Real-IP          $remote_addr;
    proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Host   $host;
    proxy_set_header    X-Forwarded-Server $host;
    proxy_set_header    X-Forwarded-Port   $server_port;
    proxy_set_header    X-Forwarded-Proto  $scheme;

    # auth local (keycloak)
    server 
        listen  80;
        server_name auth.local;

            location / 
                # keycloak
                proxy_pass http://host.docker.internal:8081/;
            

        

        server 
            listen  80;
            server_name guardian.local;

                location / 
                    # send to portal
                    rewrite ^/(.*)$ http://guardian.local/portal/$1 permanent;
                

                location /portal 
                    # guardian web-portal
                    proxy_pass http://host.docker.internal:8082;
                
            


我的安全配置类:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter 

    // Submits the KeycloakAuthenticationProvider to the AuthenticationManager
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    

    /**
     * Used by Spring Security to add Keycloak config from spring config resource (like application.properties).
     * @return
     */
    @Bean
    public KeycloakSpringBootConfigResolver KeycloakConfigResolver() 
        return new KeycloakSpringBootConfigResolver();
    

    // Specifies the session authentication strategy
    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() 
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        super.configure(http);
        http.authorizeRequests()
                .antMatchers("/portal/client*")
                .hasRole("user")
                .anyRequest()
                .permitAll();
    

还有我的 application.properties

server.port = 8082

keycloak.auth-server-url = http://auth.local/auth
keycloak.realm = myRealm
keycloak.resource = guardian-web-portal
keycloak.public-client = true
keycloak.use-resource-role-mappings = true
keycloak.principal-attribute = preferred_username

对此的任何帮助将不胜感激。我正在使用 keycloak-spring-boot-starter 12.0.4 和 spring-boot-starter-security 2.4.5。

【问题讨论】:

【参考方案1】:

尝试添加以下内容并将 permitAll() 更改为 authenticated()

.antMatchers("/login*", "/error*", "/sso*" ).permitAll()

在你的

@Override
protected void configure(HttpSecurity http) throws Exception 
    super.configure(http);
    http.authorizeRequests()
            .antMatchers("/portal/client*")
            .hasRole("user")
            .anyRequest()
            .permitAll();

所以最后你会得到:

@Override
protected void configure(HttpSecurity http) throws Exception 
    super.configure(http);
    http.authorizeRequests()
            .antMatchers("/login*", "/error*", "/sso*" ).permitAll()
            .antMatchers("/portal/client*")
            .hasRole("user")
            .anyRequest()
            .authenticated();

【讨论】:

以上是关于使用 nginx 代理的带有 keycloak 的 Spring Boot 仅在 redirect_uri localhost 时才有效的主要内容,如果未能解决你的问题,请参考以下文章

使用 nginx 反向代理后面的 keycloak 保护 nodejs 中的路由

使用 nginx 的 Keycloak 重定向 url 将转到 http 而不是 https

使用 nginx 作为反向代理和 keycloak 作为上游服务器的组合失败

如何在 keycloak 和 nginx 上配置 cors?

Keycloak NGINX 反向代理问题

代理从 nginx 容器传递到 keycloak 容器时获取 502 Bad gateway