如何使用vaadin14正确配置spring security以处理2个入口点-keyclaok和db

lymnna71  于 2021-10-10  发布在  Java
关注(0)|答案(1)|浏览(436)

我有一个vaadin14应用程序,我想在不同的url路径上启用不同类型的身份验证机制。一个是测试url,其中身份验证应使用db,另一个是使用KeyClope的生产url。
我能够让每个身份验证机制分别工作,但一旦我尝试将两者都放在一起,就会得到意想不到的结果。
在这两种情况下,我都会获得登录页面,但身份验证无法正常工作。这是我的安全配置,我做错了什么?

@Configuration
@EnableWebSecurity
public class ApplicationSecurityConfiguration {

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

    private static final String LOGIN_PROCESSING_URL = "/login";
    private static final String LOGIN_FAILURE_URL = "/login?error";
    private static final String LOGIN_URL = "/login";
    private static final String LOGOUT_SUCCESS_URL = "/login";

    /**
     * Require login to access internal pages and configure login form.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

      // Not using Spring CSRF here to be able to use plain HTML for the login page
      http.csrf().disable()

        // Register our CustomRequestCache, that saves unauthorized access attempts, so
        // the user is redirected after login.
        .requestCache().requestCache(new CustomRequestCache())

        // Restrict access to our application.
        .and().antMatcher("/test**").authorizeRequests()

        // Allow all flow internal requests.
        .requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()

        // Allow all requests by logged in users.
        .anyRequest().hasRole("USER")

        // Configure the login page.
        .and().formLogin().loginPage(LOGIN_URL).permitAll().loginProcessingUrl(LOGIN_PROCESSING_URL)
        .failureUrl(LOGIN_FAILURE_URL)

        // Configure logout
        .and().logout().logoutSuccessUrl(LOGOUT_SUCCESS_URL);
    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {

      Properties users = null;
      try {
        users = PropertiesLoaderUtils.loadAllProperties("users.properties");
        return new InMemoryUserDetailsManager(users);
      } catch (IOException e) {
        e.printStackTrace();
      }

      UserDetails user =
        User.withUsername("user")
        .password("{noop}password")
        .roles("ACTOR")
        .build();

      return new InMemoryUserDetailsManager(user);
    }

    /**
     * Allows access to static resources, bypassing Spring security.
     */
    @Override
    public void configure(WebSecurity web) {
      web.ignoring().antMatchers(
        // Vaadin Flow static resources
        "/VAADIN/**",
        // the standard favicon URI
        "/favicon.ico",
        // the robots exclusion standard
        "/robots.txt",
        // web application manifest
        "/manifest.webmanifest",
        "/sw.js",
        "/offline-page.html",
        // icons and images
        "/icons/**",
        "/images/**",
        // (development mode) static resources
        "/frontend/**",
        // (development mode) webjars
        "/webjars/**",
        // (development mode) H2 debugging console
        "/h2-console/**",
        // (production mode) static resources
        "/frontend-es5/**", "/frontend-es6/**",
        "/resources/**");
    }
  }

  @Order(1)
  @Configuration
  @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
  public static class AppKeycloakSecurity extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(
      AuthenticationManagerBuilder auth) throws Exception {

      KeycloakAuthenticationProvider keycloakAuthenticationProvider
        = keycloakAuthenticationProvider();
      keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
        new SimpleAuthorityMapper());
      auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
      return new KeycloakSpringBootConfigResolver();
    }

    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
      return new RegisterSessionAuthenticationStrategy(
        new SessionRegistryImpl());
    }

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

      http.httpBasic().disable();
      http.formLogin().disable();
      http.anonymous().disable();
      http.csrf().disable();
      http.headers().frameOptions().disable();

      http
        .antMatcher("/prod**")
        .authorizeRequests()
        .antMatchers("/vaadinServlet/UIDL/**").permitAll()
        .antMatchers("/vaadinServlet/HEARTBEAT/**").permitAll()
        .requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()
        .anyRequest().hasRole("actor");

      http
        .logout()
        .addLogoutHandler(keycloakLogoutHandler())
        .logoutUrl("/logout").permitAll()
        .logoutSuccessUrl("/");
      http
        .addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class);
      http
        .exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint());
      http
        .sessionManagement()
        .sessionAuthenticationStrategy(sessionAuthenticationStrategy());
    }
  }

}
nuypyhwy

nuypyhwy1#

在vaadin ui中导航将更改浏览器中的url,但不一定会创建针对该url的浏览器请求,从而有效地绕过spring security为该url定义的访问控制。因此,vaadin确实不适合spring提供的基于请求url的安全方法。就这个问题而言,您可以看看我为vaadin专门创建的附加spring boot security,它是为了缩小spring security和vaadin之间的差距。
但是,尽管基于url创建两个不同的spring安全上下文是相当容易的,但出于同样的原因,这对vaadin来说不会很好或者根本不会起作用。这是连我的插件都帮不上的。
更新:由于组合这两种安全上下文是您的选择,我可以提供以下解决方案(使用我的附加组件):从KeyClope示例开始,您必须执行以下操作:
改变 WebSecurityConfig 还要添加基于数据库的 AuthenticationProvider . 添加您的 UserDetailsService 应该足够了。确保给每个用户一个合适的角色。
您必须从中删除此行 application.properties : codecamp.vaadin.security.standard-auth.enabled = false 这将通过vaadin视图重新启用标准登录,而不使用keydove。
改编 KeycloakRouteAccessDeniedHandler 忽略所有不应受KeyClope保护的测试视图。
我已经在gitlab repo中准备好了所有这些内容,并删除了对解决方案要点不重要的所有内容。请参阅个人提交及其差异,以帮助关注重要的方面。

相关问题