복붙노트

[SPRING] 액세스 토큰을 발급 할 때 사용자 정보를 포함 할 수 있습니까?

SPRING

액세스 토큰을 발급 할 때 사용자 정보를 포함 할 수 있습니까?

일부 oauth2 구현에서 액세스 토큰을 발행 할 때 권한 서버가 리턴 한 응답에 대한 추가 정보를 보았습니다. 스프링 - 보안 -auth2를 사용하여이를 수행 할 수있는 방법이 있는지 궁금합니다. 액세스 토큰 응답에 일부 사용자 권한을 포함시켜 사용자가 사용하는 응용 프로그램이 사용자 권한을 관리 할 필요는 없지만 사용자는 자신의 보안 컨텍스트에서 사용자를 설정하고 자체적 인 스프링 보안을 적용 할 수 있습니다. 체크 무늬.

JWT 토큰을 사용하고 클라이언트 응용 프로그램과 적절한 정보를 공유하여 토큰에서 사용자 / 권한을 파싱하고 컨텍스트에서 설정할 수있는 또 다른 옵션이 있다고 가정합니다. 어떤 클라이언트 응용 프로그램이이 정보에 액세스 할 수 있는지 (신뢰할 수있는 응용 프로그램 만 가능) 및 AFAIK 권한 서버와 자원 서버가 JWT 토큰을 구문 분석하는 방법을 알고 있어야하는 것을 선호하기 때문에 이로 인해 더 불편할 수 있습니다.

해결법

  1. ==============================

    1.다음과 같이 사용자 지정 TokenEnhancer를 구현해야합니다.

    다음과 같이 사용자 지정 TokenEnhancer를 구현해야합니다.

    public class CustomTokenEnhancer implements TokenEnhancer {
    
        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
            User user = (User) authentication.getPrincipal();
            final Map<String, Object> additionalInfo = new HashMap<>();
    
            additionalInfo.put("customInfo", "some_stuff_here");
            additionalInfo.put("authorities", user.getAuthorities());
    
            ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
    
            return accessToken;
        }
    
    }
    

    AuthorizationServerConfigurerAdapter에 해당 설정 도구가있는 Bean으로 추가하십시오

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
    
        // Some autowired stuff here
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            // @formatter:off
            endpoints
                // ...
                .tokenEnhancer(tokenEnhancer());
            // @formatter:on
        }
    
        @Bean
        @Primary
        public AuthorizationServerTokenServices tokenServices() {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            // ...
            tokenServices.setTokenEnhancer(tokenEnhancer());
            return tokenServices;
        }
    
        // Some @Bean here like tokenStore
    
        @Bean
        public TokenEnhancer tokenEnhancer() {
            return new CustomTokenEnhancer();
        }
    
    }
    

    다음 컨트롤러 (예를 들어)

    @RestController
    public class MyController {
    
        @Autowired
        private AuthorizationServerTokenServices tokenServices;
    
        @RequestMapping(value = "/getSomething", method = RequestMethod.GET)
        public String getSection(OAuth2Authentication authentication) {
            Map<String, Object> additionalInfo = tokenServices.getAccessToken(authentication).getAdditionalInformation();
    
            String customInfo = (String) additionalInfo.get("customInfo");
            Collection<? extends GrantedAuthority> authorities = (Collection<? extends GrantedAuthority>) additionalInfo.get("authorities");
    
            // Play with authorities
    
            return customInfo;
        }
    
    }
    

    필자는 개인적으로 JDBC TokenStore를 사용하여 "여기 autowired stuff"이 일부 @Autowired Datasource, PasswordEncoder 및 그 외의 것에 해당합니다.

    희망이 도움이!

  2. ==============================

    2.Spring의 JwtAccessTokenConverter 나 DefaultAccessTokenConverter를 사용하고 있다면 커스텀 CustomTokenEnhancer를 추가하고 (첫 번째 응답 참조) TokenEnhancerChain을 다음과 같이 적용 할 수 있습니다 :

    Spring의 JwtAccessTokenConverter 나 DefaultAccessTokenConverter를 사용하고 있다면 커스텀 CustomTokenEnhancer를 추가하고 (첫 번째 응답 참조) TokenEnhancerChain을 다음과 같이 적용 할 수 있습니다 :

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        enhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer(), accessTokenConverter()));
    
        endpoints.tokenStore(tokenStore())
                .tokenEnhancer(enhancerChain)
                .authenticationManager(authenticationManager);
    }
    
    @Bean
    protected JwtAccessTokenConverter jwtTokenEnhancer() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("my_signing_key");
        return converter;
    }
    
    @Bean public TokenEnhancer customTokenEnhancer() {
        return new CustomTokenEnhancer();
    }
    

    또 다른 해결책은 Spring의 JwtAccessTokenConverter를 확장하고 사용자 정의 클레임으로 enhance () 메서드를 재정의하는 사용자 정의 TokenConverter를 만드는 것입니다.

    public class CustomTokenConverter extends JwtAccessTokenConverter {
    
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
    
        final Map<String, Object> additionalInfo = new HashMap<>();
        additionalInfo.put("customized", "true");
        User user = (User) authentication.getPrincipal();
        additionalInfo.put("isAdmin", user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()).contains("BASF_ADMIN"));
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
    
        return super.enhance(accessToken, authentication);
        }
    } 
    

    그리고:

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    
        endpoints.tokenStore(tokenStore())
                .tokenEnhancer(customTokenEnhancer())
                .authenticationManager(authenticationManager);
    }
    
    @Bean public CustomTokenConverter customTokenEnhancer() {
        return new CustomTokenConverter();
    }
    
  3. ==============================

    3.함께 :

    함께 :

    @Bean
    public TokenEnhancer tokenEnhancer() {
       return new CustomTokenEnhancer();
    }
    

    포함시켜야합니다.

    @Bean
    public DefaultAccessTokenConverter accessTokenConverter() {
        return new DefaultAccessTokenConverter();
    }
    

    엔드 포인트에 모든 것을 추가하십시오. config :

    @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    
            endpoints
                    .tokenStore(tokenStore)
                    .tokenEnhancer(tokenEnhancer())
                    .accessTokenConverter(accessTokenConverter())
                    .authorizationCodeServices(codeServices)
                    .authenticationManager(authenticationManager)
            ;
        }
    

    이를 사용하지 않으면 CustomTokenEnhancer가 작동하지 않습니다.

  4. ==============================

    4.package com.security; import java.util.HashMap; import java.util.Map; org.springframework.security.core.userdetails.User를 가져 오십시오; org.springframework.security.oauth2.common.DefaultOAuth2AccessToken을 가져 오십시오. import org.springframework.security.oauth2.common.OAuth2AccessToken; org.springframework.security.oauth2.provider.OAuth2Authentication 가져 오기 org.springframework.security.oauth2.provider.token.TokenEnhancer 가져 오기 import org.springframework.stereotype.Component; @구성 요소 공용 클래스 CustomTokenEnhancer는 TokenEnhancer { @보수 공개 OAuth2AccessToken 향상 (OAuth2AccessToken 액세스 토큰, OAuth2 인증 인증) { // TODO 자동 생성 메소드 스텁 사용자 사용자 = (사용자) authentication.getPrincipal ();         최종지도 additionalInfo = new HashMap <> ();         additionalInfo.put ( "customInfo", "some_stuff_here");         additionalInfo.put ( "authorities", user.getAuthorities ());         ((DefaultOAuth2AccessToken) accessToken) .setAdditionalInformation (additionalInfo);         return accessToken; } }

    package com.security; import java.util.HashMap; import java.util.Map; org.springframework.security.core.userdetails.User를 가져 오십시오; org.springframework.security.oauth2.common.DefaultOAuth2AccessToken을 가져 오십시오. import org.springframework.security.oauth2.common.OAuth2AccessToken; org.springframework.security.oauth2.provider.OAuth2Authentication 가져 오기 org.springframework.security.oauth2.provider.token.TokenEnhancer 가져 오기 import org.springframework.stereotype.Component; @구성 요소 공용 클래스 CustomTokenEnhancer는 TokenEnhancer { @보수 공개 OAuth2AccessToken 향상 (OAuth2AccessToken 액세스 토큰, OAuth2 인증 인증) { // TODO 자동 생성 메소드 스텁 사용자 사용자 = (사용자) authentication.getPrincipal ();         최종지도 additionalInfo = new HashMap <> ();         additionalInfo.put ( "customInfo", "some_stuff_here");         additionalInfo.put ( "authorities", user.getAuthorities ());         ((DefaultOAuth2AccessToken) accessToken) .setAdditionalInformation (additionalInfo);         return accessToken; } }

    다음은 xml 구성입니다.

                     

    그래서 토큰에 추가 정보를 추가 할 수있었습니다.

  5. from https://stackoverflow.com/questions/28492116/can-i-include-user-information-while-issuing-an-access-token by cc-by-sa and MIT license