Используйте несколько HttpSessionIdResolver с Spring - PullRequest
2 голосов
/ 14 апреля 2020

Я хочу использовать HTTPSessionIdResolver для всего, что находится в "/ api **", и для всего остального стандартного CookieResolver.

Как это возможно, чтобы две конфигурации использовали разные распознаватели? При моем текущем подходе все использует X-AUTH.

Я попытался понять реализацию в Spring, и я оказался в SessionRepositoryFilter, но из этого фильтра создается только один экземпляр, поэтому существует только один преобразователь.

    @EnableWebSecurity
    public class TestConfig {

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

        @Bean
        @Primary
        public HeaderHttpSessionIdResolver xAuth() {
            return HeaderHttpSessionIdResolver.xAuthToken();
        }

        @Bean
        @Primary
        public MapSessionRepository mapSessionRepository(){
            return new MapSessionRepository(new HashMap<>());
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/service/json/**")
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .httpBasic()
                .and()
                .csrf()
                .disable();
        }

    }

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

        @ConfigurationProperties(prefix = "spring.datasource")
        @Bean
        @Primary
        public DataSource dataSource() {
            return DataSourceBuilder
                    .create()
                    .build();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                .antMatchers("/css/**", "/user/registration", "/webfonts/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
                .logout()
                .permitAll();
        }

        @Bean
        public BCryptPasswordEncoder bcrypt() {
            return new BCryptPasswordEncoder();
        }

        @Bean
        public JdbcUserDetailsManager userDetailsManager() {
            JdbcUserDetailsManager manager = new UserDetailsManager(dataSource());
            manager.setUsersByUsernameQuery("select username,password,enabled from users where username=?");
            manager.setAuthoritiesByUsernameQuery("select username,authority from authorities where username = ?");
            return manager;
        }

        @Autowired
        public void initialize(AuthenticationManagerBuilder builder) throws Exception {
            builder.userDetailsService(userDetailsManager()).passwordEncoder(bcrypt());
        }
     }
  }

Я мог бы переместить логи c в один распознаватель, который делегирует работу существующим распознавателям, но это кажется вздорным?

public class SmartHttpSessionIdResolver implements HttpSessionIdResolver {

    private static final String HEADER_X_AUTH_TOKEN = "X-Auth-Token";
    private static final CookieHttpSessionIdResolver cookie = new CookieHttpSessionIdResolver();
    private static final HeaderHttpSessionIdResolver xauth = HeaderHttpSessionIdResolver.xAuthToken();

    @Override
    public List<String> resolveSessionIds(HttpServletRequest request) {
        if (isXAuth(request)) {
            return xauth.resolveSessionIds(request);
        }
        return cookie.resolveSessionIds(request);
    }

    @Override
    public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
        if (isXAuth(request)) {
            xauth.setSessionId(request, response, sessionId);
        } else {
            cookie.setSessionId(request, response, sessionId);
        }
    }

    @Override
    public void expireSession(HttpServletRequest request, HttpServletResponse response) {
        if (isXAuth(request)) {
            xauth.expireSession(request, response);
        } else {
            cookie.expireSession(request, response);
        }
    }

    private boolean isXAuth(HttpServletRequest request) {
        return request.getHeader(HEADER_X_AUTH_TOKEN) != null;
    }
}

1 Ответ

1 голос
/ 22 апреля 2020

Как вы упомянули выше, на основе кода класса * SessionRepositoryFilter , ясно, что он поддерживает только один HttpSessionIdResolver. В результате, если вы используете только один «SessionRepositoryFilter», кажется, что вы предлагаете единственный вариант. Хотя это сработает, это выглядит несколько странно, а также, если вы действительно хотите использовать «HTTPSessionIdResolver» для всего, что находится в «/ api **», то это не гарантирует этого.

Поскольку класс «SessionRepositoryFilter» фактически является фильтром, я предлагаю проверить, можете ли вы создать два компонента Spring для класса «SessionRepositoryFilter». Один будет использоваться для всех конечных точек HTTP по шаблону "/ api *", а другой - для всех других путей. Затем вы можете использовать «HttpSessionIdResolver» и «CookieSessionIdResolver» соответственно. Вы можете найти пример для определения различных фильтров на основе шаблонов URL здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...