代码之家  ›  专栏  ›  技术社区  ›  nosrat

从spring授权服务器注销后,ID_token(jwt)仍然有效

  •  0
  • nosrat  · 技术社区  · 1 年前

    下面是我的源代码

        @PostMapping(value = "/logout", produces = MediaType.APPLICATION_JSON_VALUE)
            public ResponseDTO usingRefreshTokenLogout(@RequestBody LogoutRequestDTO logoutRequestDTO) throws ServletException {
                log.info("going to logout user");
                return keycloakService.logoutFromSSO(logoutRequestDTO);
            }
    
        @Override
        public ResponseDTO logoutFromSSO(LogoutRequestDTO logoutRequestDTO) throws ServletException {
            logoutRequestDTO.setClient_id(clientId);
            logoutRequestDTO.setClient_secret(clientSecret);
            ResponseEntity<String> response =  loginClient.logout(logoutRequestDTO);
            if(response.getStatusCode() == HttpStatus.NO_CONTENT) {
                log.info("response : {}", response.getBody());
                return new SuccessResponseDTO("Logout request successful");
            }else {
                log.info("response : {}", response.getBody());
                return new SuccessResponseDTO("Logout request failed with status code: " +  
                response.getStatusCode());
            }
        }
    
        import com.tcg.admin.dto.LogoutRequestDTO;
        import feign.Headers;
        import org.springframework.cloud.openfeign.FeignClient;
        import org.springframework.http.MediaType;
        import org.springframework.http.ResponseEntity;
        import org.springframework.web.bind.annotation.PostMapping;
        import org.springframework.web.bind.annotation.RequestBody;
    
        @FeignClient(name = "sessionFeignClient", url = "${client.post.base.url}")
        public interface LoginClient {
    
        @PostMapping(value = "/logout",
                consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
        ResponseEntity<String> logout(@RequestBody LogoutRequestDTO logoutRequestDTO);
      }
    
      
    
         @Getter
            @Setter
            @AllArgsConstructor
            @NoArgsConstructor
            @Builder
            public class LogoutRequestDTO {
                private String refresh_token;
                private String client_id;
                private String client_secret;
            }
    

    下面是我的注销网址

    http://base-url/realms/my-realm-name/protocol/openid-connect/logout

    我正在尝试实现注销功能。使用刷新令牌,我可以注销,但注销后我的访问令牌不会失效。并且使用该访问令牌,我可以访问其他资源。如果我按照钥匙斗篷医生的说法通过。 https://www.keycloak.org/docs/latest/securing_apps/index.html#logout 然后我得到了邮递员对注销确认的回复。如果有人帮我解决这个问题。 我的钥匙斗篷版本是15.0.2

    提前表示感谢

    0 回复  |  直到 2 年前
        1
  •  1
  •   Gary Archer    2 年前

    JWT访问令牌是无状态的,在用户注销时不会失效。API将继续接受它们。

    您可以随时撤销刷新令牌,包括注销时。下次当一方尝试使用刷新令牌来获取访问令牌时,它将失败。

    假设您正在编写web客户端,两种常见且最简单的最佳实践如下:

    • 保持访问令牌的有效期较短,例如15分钟,这样它们在注销后很长一段时间内都无效

    • 根据 best practices ,这也有助于确保注销时立即拒绝所有后端访问

    • 客户端可以在注销时丢弃所有令牌(如ch4mp在下面的评论中所指出的)

    高级控制

    还可以使用引用令牌格式的访问令牌。这样的令牌需要在授权服务器上进行自省,并且可以立即检测吊销事件。

    反思通常在API网关中完成,然后将结果缓存为具有相同令牌的未来请求。

    在撤销事件之后,授权服务器可以通知API网关,该网关可以从其缓存中移除该客户端+用户组合的令牌。

        2
  •  0
  •   Kafarson    2 年前

    我知道这个“解决方案”是一个破解,但可能会帮助你解决问题。

    您可以将令牌和is_activate标志持久化到数据库中。 当您注销用户时,您可以更改特定令牌的标志,若令牌处于非活动状态,则用户不应该访问API。

    PS:在密钥斗篷API中我发现了一次.无效(令牌)方法:

        Keycloak keycloak = KeycloakBuilder.builder()
                .realm(realm)
                .serverUrl(serverURL)
                ...
                .build();
    
        keycloak.tokenManager()
                .invalidate(token);
    
        3
  •  0
  •   w08r    2 年前

    这就是围绕JWT使用的大量批评的本质。请参阅“ Stop using JWT for sessions “,它的续集,以及一堆其他指导。你需要一个会话数据库,作为 Kafarson hinted at ,或者你需要依赖超时,这对你的安全态势来说是一个很大的问题。