我有一个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());
}
}
}
1条答案
按热度按时间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中准备好了所有这些内容,并删除了对解决方案要点不重要的所有内容。请参阅个人提交及其差异,以帮助关注重要的方面。