首页 文章

如何在Rest模板中重用来自user(authorization_code)的oauth2令牌

提问于
浏览
1

我有3个申请

  • 前端申请

  • OAuth2身份验证服务器

  • REST api(RepositoryRestResources)

我的用户必须先登录才能使用前端应用程序 . 这通过SSO发生 . 他们会收到一个令牌,该令牌在被允许之前由客户验证 .

我想重用此令牌来发出api请求 . 我的REST api应用程序使用相同的SSO登录进行保护(它是前端客户端的资源)但我不知道如何“添加授权头”以在我用于api请求的RestTemplate中使用 .

我像这样创建我的restTemplate:

public static RestTemplate build()
    {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.registerModule(new Jackson2HalModule());
        mapper.registerModule(new JavaTimeModule());
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
        converter.setObjectMapper(mapper);
        return new RestTemplate(Arrays.asList(converter));
    }

我的资源服务器配置:

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
{

    @Value("${resource.id}")
    private String resourceId;

    @Override
    public void configure(HttpSecurity http) throws Exception
    {
        http
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS).permitAll()
                .anyRequest().authenticated()
                .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception
    {
        resources.resourceId(resourceId);
    }


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


    @Bean
    public static JwtAccessTokenConverter accessTokenConverter()
    {
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "somesecret".toCharArray());
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();

        converter.setKeyPair(keyStoreKeyFactory.getKeyPair("pair"));
        return converter;
    }

    @Bean
    public static TokenStore tokenStore()
    {
        return new JwtTokenStore(accessTokenConverter());
    }

}

2 回答

  • 2

    我使用intercepter修复它,从安全上下文中手动添加Token .

    RestTemplate restTemplate = new RestTemplate();
    restTemplate.getInterceptors().add(new OAuthInterceptor());
    

    其中拦截器定义为:

    public class OAuthInterceptor implements ClientHttpRequestInterceptor
    {
    
        @Autowired
        private AuthenticationHolder holder;
    
        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException
        {
            if (holder.getToken() == null)
            {
                //throw new IOException("Token not set");
                System.out.println("##################### Token not set! ###################");
            }
            else
            {
                System.out.println("##################### Token found: " + holder.getToken());
                HttpHeaders headers = request.getHeaders();
                headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + holder.getToken());
            }
    
            return execution.execute(request, body);
        }
    }
    

    我使用我在客户端应用程序中实现的界面:

    public interface AuthenticationHolder
    {
        String getToken();
    }
    
    @Bean
    public AuthenticationHolder getAuthenticationHolder()
    {
        return () ->
        {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if(authentication != null && authentication.getDetails() instanceof OAuth2AuthenticationDetails)
            {
                return ((OAuth2AuthenticationDetails) authentication.getDetails()).getTokenValue();
            }
            return null;
        };
    }
    
  • 0

    您可以在方法的顶部使用 @PreAuthorize(ROLE) ,因此当调用此方法时,他将与令牌一样,然后他将检查提供的令牌是否具有使用该方法所需的ROLE .

    当然,您需要配置API以连接到OAuth数据库 .

    例:

    @PreAuthorize("ROLE_ADMIN") public void deleteAll(){ ... }

相关问题