Фильтр CAS не перехватывает служебный билет при развертывании войны - PullRequest
0 голосов
/ 25 апреля 2019

У меня есть приложение Spring Boot, которое проходит проверку подлинности на сервере CAS. Когда я выполняю «mvn spring-boot:run», вход выполняется правильно:

  1. Позвоните на URL_1_APP

  2. Перенаправление на cas / login

  3. Заполните учетные данные и отправьте

  4. Перенаправление на Service_id_path? Ticket = ST-XX -...

  5. Перенаправление на запрошенный URL URL_1_APP

Но когда я выполняю "mvn package" и развертываю войну на сервере tomcat, последнее перенаправление не выполняется:

  1. Позвонить на URL_1_APP
  2. Перенаправление на cas / login
  3. Заполните учетные данные и отправьте
  4. Перенаправление на Service_id_path? Ticket = ST-XX -... -> Перенаправление на URL_1_APP никогда не выполняется

Я использую: Пружинный ботинок 1.5.2. Tomcat 9.0.16 JDK 11

Это мой начальный класс:

package com.qim.ptp;

import com.qim.ptp.config.YmlPropertyFactory;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.event.EventListener;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;

import javax.servlet.http.HttpSessionEvent;

@ComponentScan(basePackages = {"com.qim"})
@ServletComponentScan
@SpringBootApplication
@EnableJpaRepositories(basePackages = {"com.qim.ptp.repository"})
@PropertySource(factory = YmlPropertyFactory.class, value = "file:${config.path}")
public class BackApplication extends SpringBootServletInitializer {

    private static final Logger log = LoggerFactory.getLogger(BackApplication.class);

    @Value("${qim.cas.service-id}")
    private String serviceId;

    @Value("${qim.cas.path.base}")
    private String casBasePath;

    @Value("${qim.cas.path.login}")
    private String casLoginPath;

    @Value("${qim.cas.path.logout}")
    private String casLogoutPath;

    @Value("${qim.cas.admin.username}")
    private String casUsername;

    @Value("${qim.cas.admin.password}")
    private String casPassword;

    @Value("${qim.cas.admin.role}")
    private String casRole;

    @Value("${qim.cas.admin.key}")
    private String casKey;

    @Value("${qim.paths.base.version.v1}")
    private String basePath;

    @Value("${qim.paths.logout}")
    private String logoutPath;

    @Value("${server.port}")
    private String serverPort;

    public static void main( String[] args ) {
        log.info("Init application");
        SpringApplication.run(BackApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(BackApplication.class);
    }


    @Bean
    public ServiceProperties serviceProperties() {
        ServiceProperties serviceProperties = new ServiceProperties();
        serviceProperties.setService("http://localhost:"+serverPort+"/kaka");
        serviceProperties.setSendRenew(false);
        serviceProperties.setAuthenticateAllArtifacts(true);
        return serviceProperties;
    }

    @Bean
    @Primary
    public AuthenticationEntryPoint authenticationEntryPoint(
            ServiceProperties sP) {
        CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
        entryPoint.setLoginUrl(casBasePath+casLoginPath);
        entryPoint.setServiceProperties(sP);
        return entryPoint;
    }

    @Bean
    public TicketValidator ticketValidator() {
        return new Cas30ServiceTicketValidator(casBasePath);
    }

    @Bean
    public CasAuthenticationProvider casAuthenticationProvider() {

        CasAuthenticationProvider provider = new CasAuthenticationProvider();
        provider.setServiceProperties(serviceProperties());
        provider.setTicketValidator(ticketValidator());
        provider.setUserDetailsService(
                s -> new User(casUsername, casPassword, true, true, true, true,
                        AuthorityUtils.createAuthorityList(casRole)
                )
        );
        provider.setKey(casKey);
        return provider;
    }

    @Bean
    public SecurityContextLogoutHandler securityContextLogoutHandler() {
        return new SecurityContextLogoutHandler();
    }

    @Bean
    public LogoutFilter logoutFilter() {
        LogoutFilter logoutFilter = new LogoutFilter(
                casBasePath+casLogoutPath,
                securityContextLogoutHandler());
        logoutFilter.setFilterProcessesUrl(basePath+logoutPath);
        return logoutFilter;
    }

    @Bean
    public SingleSignOutFilter singleSignOutFilter() {
        SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
        singleSignOutFilter.setCasServerUrlPrefix(casBasePath);
        singleSignOutFilter.setIgnoreInitConfiguration(true);
        return singleSignOutFilter;
    }

    @EventListener
    public SingleSignOutHttpSessionListener singleSignOutHttpSessionListener(
            HttpSessionEvent event) {
        return new SingleSignOutHttpSessionListener();
    }

}

В этом классе я настраиваю фильтры Spring Security:

package com.qim.ptp.config;

import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
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.context.annotation.Primary;
import org.springframework.context.event.EventListener;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.servlet.http.HttpSessionEvent;
import java.util.Arrays;

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private AuthenticationProvider authenticationProvider;
    private AuthenticationEntryPoint authenticationEntryPoint;
    private SingleSignOutFilter singleSignOutFilter;
    private LogoutFilter logoutFilter;
    private CasAuthenticationFilter filter;

    @Value("${qim.paths.base.version.v1}")
    private String basePath;

    @Value("${qim.paths.logout}")
    private String logoutPath;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .addFilter(this.filter)
                .authorizeRequests()
                .regexMatchers("/.*")
                .authenticated()
                .and()
                .authorizeRequests()
                .regexMatchers("/")
                .permitAll()
                .and()
                .httpBasic()
                .authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .logout().logoutSuccessUrl(basePath+logoutPath)
                .and()
                .addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class)
                .addFilterBefore(logoutFilter, LogoutFilter.class);
    }

    @Autowired
    public SecurityConfig(CasAuthenticationProvider casAuthenticationProvider, AuthenticationEntryPoint eP,
                          LogoutFilter lF
            , SingleSignOutFilter ssF
    ) {
        this.authenticationProvider = casAuthenticationProvider;
        this.authenticationEntryPoint = eP;

        this.logoutFilter = lF;
        this.singleSignOutFilter = ssF;

    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider);
    }

    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return new ProviderManager(Arrays.asList(authenticationProvider));
    }

    @Bean
    public CasAuthenticationFilter casAuthenticationFilter(ServiceProperties sP) throws Exception {
        CasAuthenticationFilter filter = new CasAuthenticationFilter();
        filter.setServiceProperties(sP);
        filter.setFilterProcessesUrl("/kaka");
        filter.setAuthenticationManager(authenticationManager());
        this.filter = filter;
        return filter;
    }

}

Заранее спасибо.

1 Ответ

0 голосов
/ 26 апреля 2019

Произошла ошибка, поскольку при развертывании войны на сервере для доступа к приложению включается контекстный путь: ресурс http://localhost:9000/hello изменяется на http://localhost:9000/application-version/hello

Таким образом, изменениенеобходимо в методе свойств сервиса:

@Bean
public ServiceProperties serviceProperties() {
    ServiceProperties serviceProperties = new ServiceProperties();
    serviceProperties.setService("http://localhost:"+serverPort+"/application-version/kaka");
    serviceProperties.setSendRenew(false);
    serviceProperties.setAuthenticateAllArtifacts(true);
    return serviceProperties;
}

Но нет необходимости включать этот путь контекста в метод фильтра cas:

@Bean
public CasAuthenticationFilter casAuthenticationFilter(ServiceProperties sP) throws Exception {
    CasAuthenticationFilter filter = new CasAuthenticationFilter();
    filter.setServiceProperties(sP);
    filter.setFilterProcessesUrl("/kaka");
    filter.setAuthenticationManager(authenticationManager());
    this.filter = filter;
    return filter;
}
...