是否可以仅在特定网址上触发x509身份验证?

时间:2019-04-05 12:13:33

标签: spring authentication spring-security x509

我有一个针对ldap服务器进行身份验证的Web应用程序。现在,我需要添加带有CAC卡提供的x509证书的身份验证。

到目前为止,我已经实现了:打开应用程序时,要求输入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;
    }

}

我的tomcat连接器看起来像这样:

    <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上触发证书身份验证,而不是在打开应用程序时触发。

0 个答案:

没有答案