【问题标题】:Use Keycloak and JWT Statelessly in Spring Boot在 Spring Boot 中无状态使用 Keycloak 和 JWT
【发布时间】:2022-08-03 09:12:34
【问题描述】:

我需要使用 Keycloak,并且更喜欢在我的 Spring Boot 应用程序中使用无状态 JWT 令牌。我可以让它在会话中正常运行,但是在转换它时我需要帮助

  • 强制 Spring Boot Security 检查登录
  • 允许 /logout URL(转到 Keycloak)

我的代码“运行”,但是当我点击初始页面时,我看到的日志消息似乎表明它没有检测到任何登录迹象。发生这种情况时,我想强制使用 Spring启动以重定向到登录页面,就像这是一个有状态的应用程序一样。

org.springframework.web.servlet.FrameworkServlet: Failed to complete request: java.lang.NullPointerException: Cannot invoke \"org.springframework.security.authentication.AbstractAuthenticationToken.getName()\" because \"authenticationToken\" is null
org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper: Did not store anonymous SecurityContext
org.springframework.security.web.context.SecurityContextPersistenceFilter: Cleared SecurityContextHolder to complete request
org.apache.juli.logging.DirectJDKLog: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException: Cannot invoke \"org.springframework.security.authentication.AbstractAuthenticationToken.getName()\" because \"authenticationToken\" is null] with root cause
java.lang.NullPointerException: Cannot invoke \"org.springframework.security.authentication.AbstractAuthenticationToken.getName()\" because \"authenticationToken\" is null
    

这是我的 HttpSecurity sn-p:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
        .csrf()
//      .disable().exceptionHandling().accessDeniedPage(\"/access-denied\")
        .and()
        .authorizeRequests()
        .antMatchers(\"/sso/**\").permitAll()
        .antMatchers(\"/error/**\").permitAll()
        .antMatchers(\"/css/**\",\"/contact-us\",\"/actuator/**\",\"/isalive/**\").permitAll()
        .anyRequest().authenticated()
        .and()
        .oauth2Login()
        .defaultSuccessUrl(\"/myfirstpage\",true)
        .and().exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
        .and()
        .oauth2ResourceServer().jwt();

    }

我知道我错过了一些东西,但我认为 Keycloak 提供了很多这样的东西 OOTB。初始 URL 是 /。我曾希望 .authenticated() 会强制它针对所有不允许的模式进行身份验证,但我可能错了。我错过了什么?

请注意,互联网上充斥着 Spring Boot + Keycloak 的示例(有些甚至很好)。它还有很多 Spring Boot + OAuth + Stateless JWT。它没有(我可以说)很多 Spring Boot + Keycloak + Stateless JWT。我从这个 JHipster repo 中得到了我能找到的一点点,但我觉得我错过了一些伟大的神奇步骤。

  • 您能否评论一下为什么答案不令人满意?否则,你会接受吗?

标签: spring-boot spring-security keycloak spring-security-oauth2


【解决方案1】:

资源服务器当身份验证丢失或无效(过期、错误的颁发者等)和客户应该处理重定向到授权服务器.

当您尝试将不同的 OAuth2 参与者(客户端、资源服务器和授权服务器)合并到单个应用程序中时,事情会变得一团糟。

你确定你想要一个春天吗客户(而不是 Angular / React / Vue / Flutter / 任何客户端渲染框架)?

如果是,也许你应该从分裂开始客户(显示登录、注销和 Thymeleaf 或任何页面)和资源服务器(REST API)应用程序。您将更好地理解您编写的 spring-security conf(并且可以断言它单独按预期工作)。

资源服务器配置 (REST API)

请注意Keycloak adapters for spring are deprecated

最简单的解决方案是spring-addons-webmvc-jwt-resource-server(支持多租户、默认无状态、属性中的 CORS 配置、轻松的 Keycloak 角色映射到 Spring 权限等等)。

您也可以直接使用spring-boot-starter-oauth2-resource-server,但它需要more java conf

客户端配置(包括登录和注销的页面)

  • 如果保留 Spring,请参阅 spring-boot 文档:它清晰且始终是最新的(与大多数教程相反)
  • 如果使用“现代”客户端框架,请从certified list 中找到一个库

我有一个完整的示例(带有 spring RESTful API 的 Ionic-Angular UI)there,但作为初学者可能有点复杂。

【讨论】:

    【解决方案2】:

    您将需要 spring-security 和 keycloak-adapter 这个指南有完整的解释如何设置和保护它

    https://keepgrowing.in/java/springboot/keycloak-with-spring-boot-1-configure-spring-security-with-keycloak/

    【讨论】:

    • 不要将 Keycloak 适配器用于弹簧,它已被弃用:github.com/keycloak/keycloak/discussions/10187
    • @ch4mp 我度假回来后会试试这个。虽然这看起来是一个经过深思熟虑的答案,但我担心我的应用程序会在未经授权的情况下直接重定向调用者。如果这不是无状态的 jwt,Spring Security 和/或 Keycloak 会处理这个问题。我还没有完全消化你的回复,所以我还没有接受它,尽管我在每个请求中检查令牌的想法似乎否定了底层框架的效用。
    • 我忘了添加我的应用程序是服务器端百里香叶应用程序。
    • @Woodsman 您的 Thymeleaf 应用程序是 OAuth2 client。正如我的回答中所述,将未经授权的用户重定向到授权服务器是客户端角色。
    • 好的,那么我如何显式检查令牌是否存在,获取正确的重定向 URL,然后显式将其发送回客户端?我不知道为什么,因为我在做无状态的 JWT,我必须这样做。同样,客户端会在框架的帮助下执行此操作。
    猜你喜欢
    • 2018-03-27
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 2022-11-25
    • 2019-07-15
    • 2020-01-11
    • 2018-12-29
    • 2020-06-19
    相关资源
    最近更新 更多