source

스프링 키클로크:사용자 ID 가져오기

ittop 2023. 10. 9. 23:31
반응형

스프링 키클로크:사용자 ID 가져오기

저는 Spring Boot Web 서비스를 개발했고, 접근 관리를 위해 Keycloock을 사용합니다.웹 사이트는 일부 사용자 데이터를 데이터베이스에 저장합니다.로그인한 사용자와 이 데이터를 연결하려고 합니다.

데이터와 함께 사용자 이름을 저장하는 순간.하지만 저는 사용자 이름 대신 사용자 ID를 저장하고 싶습니다.내가 어떻게 그럴 수 있을까?

이를 통해 SecurityContext를 가져오려고 합니다.

@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public KeycloakSecurityContext getKeycloakSecurityContext() {
    return ((KeycloakPrincipal<KeycloakSecurityContext>) getRequest().getUserPrincipal()).getKeycloakSecurityContext();
}

하지만 오류가 발생합니다.

There was an unexpected error (type=Internal Server Error, status=500).
Error creating bean with name 'scopedTarget.getKeycloakSecurityContext'
defined in com.SiteApplication: Bean instantiation via factory method
failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [org.keycloak.KeycloakSecurityContext]: Factory method
'getKeycloakSecurityContext' threw exception; nested exception is
java.lang.ClassCastException:
org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken
cannot be cast to org.keycloak.KeycloakPrincipal

이게 바른 길이야?무엇이 부족합니까?

감사해요!

위의 것보다 훨씬 간단한 해결책을 찾았습니다.

    @GetMapping
    public ResponseEntity getEndpoint(String someParam, HttpServletRequest request) {
        KeycloakAuthenticationToken principal = (KeycloakAuthenticationToken) request.getUserPrincipal();
        String userId = principal.getAccount().getKeycloakSecurityContext().getIdToken().getSubject();

        //....do something

        return new ResponseEntity(HttpStatus.OK);
    }

내 생각에 당신이 위에 있는 예외는 당신이 캐스팅하려고 하기 때문인 것 같습니다.getRequest().getUserPrincipal()로.KeycloakPrincipal<KeycloakSecurityContext>그것이 활자인 동안에는KeycloakAuthenticationToken,그렇게((KeycloakAuthenticationToken) getRequest().getUserPrincipal())효과가 있을 겁니다.

저도 우리 코드에 비슷한 걸 해봤어요.

public class AuthenticationTokenProcessingFilter extends GenericFilterBean {

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

            if (!(request instanceof HttpServletRequest)) {
                throw new RuntimeException("Expecting a HTTP request");
            }

            RefreshableKeycloakSecurityContext context = (RefreshableKeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());

            if (context == null) {
                handleNoSecurityContext(request, response, chain);
                return;
            }

            AccessToken accessToken = context.getToken();
            Integer userId = Integer.parseInt(accessToken.getOtherClaims().get("user_id").toString());

            chain.doFilter(request, response);
        }

}

이 작업을 수행하기 전에 먼저 다음을 추가해야 합니다.user_id키클록에 의해 발행되는 액세스 토큰.아래 스크린샷과 같이 맵퍼를 통해 할 수 있습니다.

configuration for property mapper

또한 위의 프로세싱 필터를 응용프로그램 라이프사이클에 추가하는 것을 잊지 마십시오.@Bean응용 프로그램 클래스에 메서드를 지정합니다.

@Configuration
@EnableAutoConfiguration(exclude = {FallbackWebSecurityAutoConfiguration.class, SpringBootWebSecurityConfiguration.class, DataSourceAutoConfiguration.class})
@ComponentScan
@EnableAsync
public class MyServiceClass {

    public static void main(String[] args) {
        Properties properties = new Properties();
        new SpringApplicationBuilder(MyServiceClass.class)
                .properties(properties)
                .bannerMode(Banner.Mode.OFF)
                .run(args);
    }


    @Bean
    public AuthenticationTokenProcessingFilter authFilter() {
        return new AuthenticationTokenProcessingFilter();
    }

}

위의 모든 솔루션들은 2년 전에는 사용하지 않던 (매우) Keycloak Spring 어댑터를 사용하고 있습니다.

2 키클로크 스프링 어댑터의 대안으로, 두 어댑터 모두 토큰 클레임에 매우 쉽게 접근할 수 있습니다.Authentication스프링이 주입한 "자동으로"@Controller메서드 매개 변수입니다.

spring-addons-webmvc-jwt-resource-server

여기 샘플: 속성에서 구성할 수 있는 거의 모든 것

    @GetMapping
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity getEndpoint(OAuthentication<OpenidClaimSet> auth) {
        final var preferredUsername = auth.getClaims().getPreferredUsername();
        final var subject = auth.getClaims().getSubject();
        //....do something
        return new ResponseEntity(HttpStatus.OK);
    }

spring-boot-starter-oauth2-resource-server

샘플: 훨씬 더 많은 Java 구성이 필요합니다.

    @GetMapping
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity getEndpoint(JwtAuthenticationToken auth) {
        final var preferredUsername = auth.getToken().getClaimAsString(StandardClaimNames.SUB);
        final var subject = auth.getToken().getClaimAsString(StandardClaimNames.PREFERRED_USERNAME);
        //....do something
        return new ResponseEntity(HttpStatus.OK);
    }

언급URL : https://stackoverflow.com/questions/45802797/spring-keycloak-get-user-id

반응형