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

时间:2017-06-22 10:36:50

标签: spring spring-boot spring-security spring-data-rest spring-security-oauth2

我有3个申请

  1. 前端申请
  2. OAuth2身份验证服务器
  3. REST api(RepositoryRestResources)
  4. 我的用户必须先登录才能使用前端应用程序。这通过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 个答案:

答案 0 :(得分: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;
    };
}

答案 1 :(得分:0)

你可以使用方法顶部的document.querySelector('img:nth-child('+Math.floor(Math.random()*5+1)+')').style.display = 'inline-block'; ,所以当这个方法被调用时,他会像Token那样检查提供的Token是否有必要的ROLE来使用这个方法。

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

示例:

@PreAuthorize(ROLE)