Интегрируйте весенний облачный шлюз с oauth2 - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь реализовать шлюз для моих служб данных.Все мои устройства данных защищены аутентификацией JWT (т. Е. Каждый запрос должен иметь заголовок «Авторизация», в противном случае устройства данных отвечают «Несанкционированный»).Я хотел бы, чтобы мой шлюз также проверял все запросы на заголовок авторизации.Как мне этого добиться?Поскольку весенний облачный шлюз основан на реактивной модели, я не могу использовать ту же конфигурацию.Ниже приведены настройки для других служб данных:

application.properties

security.jwt.signing-key=secret-key
security.resource.id=abc.dataService.com

securityConfig.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * Defines beans that protect resources using OAuth2 and JWT tokens
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private AllClaimsMappingAccessTokenConverter customAccessTokenConverter;

    @Value("${security.jwt.signing-key}")
    private String signingKey;

    @Value("${security.cors.allowedOrigins}")
    private String allowedOrigins;

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(signingKey);
        converter.setAccessTokenConverter(customAccessTokenConverter);
        return converter;
    }

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

    @Bean
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList(allowedOrigins.split(",")));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "DELETE", "PUT", "PATCH"));
        configuration.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization", "X-Auth-Token"));
        configuration.setMaxAge(TimeUnit.DAYS.toSeconds(2));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

resourceServerConfig.java

import java.io.IOException;
import java.time.Instant;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    private static final Logger LOGGER = LoggerFactory.getLogger(ResourceServerConfig.class);

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

    @Autowired
    private ResourceServerTokenServices tokenServices;

    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

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

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .cors().and()
                .requestMatchers()
                .and()
                .authorizeRequests()
                .antMatchers("/**").authenticated();
    }

    @Component("restAuthenticationEntryPoint")
    public static class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

        private static final String ERROR_JSON_TEMPLATE = "{ \"errors\": [ { \"id\": %d, \"status\": 401, \"title\": \"Not Authorized\", \"detail\": \"%s\" } ], \"meta\": {} }";

        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException ex)
                throws IOException, ServletException {
            long instant = Instant.now().toEpochMilli();
            LOGGER.error("Auth exception at {}", instant, ex);

            response.getWriter()
                    .println(String.format(ERROR_JSON_TEMPLATE, instant, ex.getMessage()));
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.flushBuffer();
        }
    }
}

TokenConverter

import java.util.Map;

import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.stereotype.Component;

@Component
public class AllClaimsMappingAccessTokenConverter extends DefaultAccessTokenConverter {

    @Override
    public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
        OAuth2Authentication authentication = super.extractAuthentication(claims);
        authentication.setDetails(claims);
        return authentication;
    }
}
...