首页 > 解决方案 > 为多个入口点配置spring security?

问题描述

我正在尝试为我的应用程序设置弹簧安全性。它有多个入口点,如下:

1. /odk/**
- 所有前缀为 /odk/ 的路由都应使用 Digest Auth 进行身份验证并相应地响应
2. /odkx/**
- 所有前缀为 /odkx/ 的路由也应该使用 Digest Auth 进行身份验证并相应地响应
3. /api/**
- 前缀为 /api/ 的所有路由都应使用 JWT 身份验证进行身份验证
4. 所有其他路由
- 与上述任何不匹配的所有路由都应使用 spring 的登录表单身份验证进行身份验证安全。

我编写的代码还为每个入口点添加了@order,以便相应地执行。我的问题是所有过滤器都被执行,而请求应该只由相关入口点处理。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {


    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**");
        web.ignoring().antMatchers("/css/**");
        web.ignoring().antMatchers("/jsp/**");
    }

    @Configuration
    @Order(1)
    public static class DigestAuthSecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Autowired
        private CustomDigestUserService customDigestUserService;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.cors().and().csrf().disable();

            http.antMatcher("/odk/**")
                .authorizeRequests().antMatchers("/odk/**")
                .fullyAuthenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilter(digestAuthFilter())BasicAuthenticationFilter.class)
                .exceptionHandling()
                .authenticationEntryPoint(digestEntryPoint());
        }


        DigestAuthenticationFilter digestAuthFilter() throws Exception {
            DigestAuthenticationFilter digestAuthenticationFilter = new DigestAuthenticationFilter();

            digestAuthenticationFilter.setUserDetailsService(customDigestUserService);
            digestAuthenticationFilter.setAuthenticationEntryPoint(digestEntryPoint());
            digestAuthenticationFilter.setPasswordAlreadyEncoded(false);
            return digestAuthenticationFilter;
        }


        DigestAuthenticationEntryPoint digestEntryPoint() {
            DigestAuthenticationEntryPoint bauth = new DigestAuthenticationEntryPoint();
            bauth.setRealmName("Digest ASIMS");
            bauth.setKey("MySecureKey");
            return bauth;
        }

    }

    @Configuration
    @Order(2)
    public static class DigestAuthSecurityConfigurationODKX extends WebSecurityConfigurerAdapter {

        @Autowired
        private CustomDigestUserService customDigestUserService;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.cors().and().csrf().disable();

            http.antMatcher("/odkx/**")
                .authorizeRequests().antMatchers("/odkx/**")
                .fullyAuthenticated()
                .and()
              .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilter(digestAuthFilterODKX())BasicAuthenticationFilter.class)
                .exceptionHandling()
                .authenticationEntryPoint(digestEntryPointODKX());
        }

        DigestAuthenticationFilter digestAuthFilterODKX() throws Exception {
            DigestAuthenticationFilter digestAuthenticationFilter = new DigestAuthenticationFilter();

            digestAuthenticationFilter.setUserDetailsService(customDigestUserService);
            digestAuthenticationFilter.setAuthenticationEntryPoint(digestEntryPointODKX());
            digestAuthenticationFilter.setPasswordAlreadyEncoded(false);
            return digestAuthenticationFilter;
        }

        DigestAuthenticationEntryPoint digestEntryPointODKX() {
            DigestAuthenticationEntryPoint bauth = new DigestAuthenticationEntryPoint();
            bauth.setRealmName("Digest ASIMS");
            bauth.setKey("MySecureKey");
            return bauth;
        }

        @Override
        public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
            authenticationManagerBuilder.userDetailsService(customDigestUserService);
        }

    }

    @Configuration
    @Order(3)
    public static class JwtAuthSecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Autowired
        private CustomUserService customUserService;

        @Autowired
        private JwtAuthenticationEntryPoint unauthorizedHandler;

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http.cors().and().csrf().disable();
            http.antMatcher("/api/**")
                    .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                    .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

            // Add our custom JWT security filter
            http.addFilterBefore(jwtAuthenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
        }

        @Autowired
        public JwtAuthenticationFilter jwtAuthenticationTokenFilterBean() throws Exception {
            return new JwtAuthenticationFilter();
        }

        @Override
        public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
            authenticationManagerBuilder.userDetailsService(customUserService).passwordEncoder(jwtPasswordEncoder());
        }

        public BCryptPasswordEncoder jwtPasswordEncoder() {
            return new BCryptPasswordEncoder();
        }

        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    }

    @Configuration
    @Order(4)
    public static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Autowired
        private CustomUserService customUserService;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.cors().and().csrf().disable();
            http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                   .loginPage("/login")
                   .permitAll()
                .and()
                .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/login");
        }

        public BCryptPasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }

        public DaoAuthenticationProvider authenticationProvider() {
            DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
            auth.setUserDetailsService(customUserService);
            auth.setPasswordEncoder(passwordEncoder());
            auth.setHideUserNotFoundExceptions(false);
            return auth;
        }

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

}

这是日志

2019-08-12 20:40:05 DEBUG org.springframework.security.web.FilterChainProxy - /odk/formList at position 6 of 12 in additional filter chain; firing Filter: 'DigestAuthenticationFilter'
2019-08-12 20:40:05 DEBUG org.springframework.security.web.authentication.www.DigestAuthenticationFilter - Digest Authorization header received from user agent: Digest username="admin", realm="Digest ASIMS", nonce="MTU2NTYyNjUwNTI1MTplNjFjYjVhODU2ODU3ZmFiNTdmMzI2NGMwZmYyOGE1MQ==", uri="/odk/formList", algorithm="MD5", qop=auth, nc=00000001, cnonce="QLgL7tFi", response="b58667867ba602024aa1c64ffd0c24a5"
2019-08-12 20:40:05 DEBUG org.springframework.security.web.authentication.www.DigestAuthenticationFilter - Extracted username: 'admin'; realm: 'Digest ASIMS'; nonce: 'MTU2NTYyNjUwNTI1MTplNjFjYjVhODU2ODU3ZmFiNTdmMzI2NGMwZmYyOGE1MQ=='; uri: '/odk/formList'; response: 'b58667867ba602024aa1c64ffd0c24a5'
Entry to CustomDigestUserServiceImpl: admin
2019-08-12 20:40:05 DEBUG org.hibernate.SQL - 
2019-08-12 20:40:13 DEBUG org.springframework.security.web.authentication.www.DigestAuthenticationFilter - Authentication success for user: 'admin' with response: 'b58667867ba602024aa1c64ffd0c24a5'
2019-08-12 20:40:31 DEBUG org.springframework.security.web.FilterChainProxy - /odk/formList at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2019-08-12 20:40:31 DEBUG org.springframework.security.web.FilterChainProxy - /odk/formList at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2019-08-12 20:40:31 DEBUG org.springframework.security.web.FilterChainProxy - /odk/formList at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2019-08-12 20:40:31 DEBUG org.springframework.security.web.authentication.AnonymousAuthenticationFilter - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ac07c509: Principal: org.springframework.security.core.userdetails.User@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: VIEW,EDIT,DELETE; Credentials: [PROTECTED]; Authenticated: false; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities'
2019-08-12 20:40:31 DEBUG org.springframework.security.web.FilterChainProxy - /odk/formList at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2019-08-12 20:40:31 DEBUG org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy - Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy@2a54a6c3
2019-08-12 20:40:31 DEBUG org.springframework.security.web.FilterChainProxy - /odk/formList at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2019-08-12 20:40:31 DEBUG org.springframework.security.web.FilterChainProxy - /odk/formList at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2019-08-12 20:40:31 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/odk/formList'; against '/odk/**'
2019-08-12 20:40:31 DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /odk/formList; Attributes: [fullyAuthenticated]
2019-08-12 20:40:31 DEBUG org.springframework.security.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
Entry to CustomUserService: admin
2019-08-12 20:40:31 DEBUG org.hibernate.SQL - 
2019-08-12 20:40:31 DEBUG org.springframework.security.authentication.dao.DaoAuthenticationProvider - Authentication failed: password does not match stored value
2019-08-12 20:40:31 DEBUG org.springframework.security.web.access.ExceptionTranslationFilter - Authentication exception occurred; redirecting to authentication entry point
org.springframework.security.authentication.BadCredentialsException: Bad credentials 

标签: javaspring-bootspring-securitydigest-authenticationjwt-auth

解决方案


推荐阅读