Можно ли запустить аутентификацию x509 только по определенному URL? - PullRequest
0 голосов
/ 05 апреля 2019

У меня есть веб-приложение, которое аутентифицировано на сервере ldap. Теперь у меня есть требование добавить аутентификацию с сертификатом x509, который предоставляется картой cac.

До сих пор я достиг: При открытии приложения меня просят ввести пин-код для сертификата на карте cac, а затем поиск ролей осуществляется через ldap. После этого я вошел в систему с правильным пользователем.

Если я нажимаю на кнопку отмены, когда меня просят подтвердить подлинность с помощью сертификата, я получаю обычную форму входа в систему для ldap и могу войти в систему, которая также работает.

Теперь моя проблема в том, что я не хочу, чтобы меня сразу же спрашивали о сертификате. Вместо этого я хочу представить форму входа в систему, а затем дать пользователю возможность войти в систему через карту cac или через обычный вход в систему ldap.

Итак, я хочу вызвать опрос для проверки подлинности сертификата только по определенному URL ...

Моя текущая конфигурация безопасности выглядит следующим образом.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${ldap.url}")
    private String ldapUrl;

    @Value("${ldap.technical.username}")
    private String ldapTechnicalUsername;

    @Value("${ldap.technical.password}")
    private String ldapTechnicalPassword;

    @Autowired
    private LdapUserDetailsMapper ldapUserDetailsMapper;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new LogMDCFilter(), AbstractPreAuthenticatedProcessingFilter.class);
        http.addFilterBefore(new AjaxExpiredFilter(), AbstractPreAuthenticatedProcessingFilter.class);

        http
                .requiresChannel()
                .antMatchers("/pages/login/certLogin.xhtml")
                .requiresSecure()
                .and()
                .x509()
                .authenticationUserDetailsService(ldapUserDetailsService());

        http
                .authorizeRequests()
                .antMatchers(
                        "/error/**",
                        "/failure/**",
                        "/login/openid/**",
                        "/javax.faces.resource/**",
                        "/services/**",
                        "/actuator/**")
                .permitAll()
                .antMatchers("/index.xhtml", "/error.xhtml").hasAuthority("IS_AUTHENTICATED_ANONYMOUSLY")
                .antMatchers("/pages/customer/customerSearch.xhtml").hasAuthority("search_customer")
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/pages/login/login.xhtml")
                .permitAll()
                .and()
                .exceptionHandling()
                .accessDeniedPage("/pages/login/accessDenied.xhtml")
                .and()
                .logout()
                .clearAuthentication(true)
                .logoutUrl("/logout")
                .logoutSuccessUrl("/pages/login/login.xhtml")
                .invalidateHttpSession(true)
                .deleteCookies("JSESSIONID")
                .permitAll()
                .and()
                .headers()
                .frameOptions()
                .sameOrigin()
                .and()
                .csrf()
                .disable();
    }

    /**
     * Used when authenicated via LDAP
     */

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth
                    .ldapAuthentication()
                    .contextSource()
                    .url(ldapUrl)
                    .managerDn(ldapTechnicalUsername)
                    .managerPassword(ldapTechnicalPassword)
                    .and()
                    .userDnPatterns("uid={0},ou=People")
                    .userSearchFilter("ismemberof")
                    .userDetailsContextMapper(ldapUserDetailsMapper)
                    .authoritiesMapper(new NullAuthoritiesMapper());
    }

    private LdapUserDetailsService ldapUserDetailsService() {
        return new LdapUserDetailsService(createLdapContextSource(), ldapUserDetailsMapper);
    }

    private LdapContextSource createLdapContextSource() {
        LdapContextSource contextSource = new LdapContextSource();
        contextSource.setUrl(ldapUrl);
        contextSource.setUserDn(ldapTechnicalUsername);
        contextSource.setPassword(ldapTechnicalPassword);
        contextSource.afterPropertiesSet();
        return contextSource;
    }

}

Мой разъем для кота выглядит так:

    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
        clientAuth="want" sslProtocol="TLS"
        keystoreFile="${catalina.home}/conf/keystore"
        keystoreType="JKS" keystorePass="password"
        truststoreFile="${catalina.home}/conf/truststore"
        truststoreType="JKS" truststorePass="truststore"/>

Настолько важно, что это работает, но я хочу, чтобы аутентификация сертификата запускалась только по определенному URL-адресу, а не при открытии приложения.

...