我用Spring Security和Keyclock配置了Vaadin 23应用程序。除了用户没有被重定向到他们启动登录过程的页面之外,一切都正常。用户总是被重定向到主页。
这是一个安全配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends VaadinWebSecurity {
private final ClientRegistrationRepository clientRegistrationRepository;
private final GrantedAuthoritiesMapper authoritiesMapper;
private final ProfileService profileService;
private String jwtAuthSecret;
SecurityConfiguration(@Value("${spring.security.jwt.auth.secret}") String jwtAuthSecret, ClientRegistrationRepository clientRegistrationRepository,
GrantedAuthoritiesMapper authoritiesMapper, ProfileService profileService) {
this.jwtAuthSecret = jwtAuthSecret;
this.clientRegistrationRepository = clientRegistrationRepository;
this.authoritiesMapper = authoritiesMapper;
this.profileService = profileService;
SecurityContextHolder.setStrategyName(VaadinAwareSecurityContextHolderStrategy.class.getName());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
// Enable OAuth2 login
.oauth2Login(oauth2Login ->
oauth2Login
.clientRegistrationRepository(clientRegistrationRepository)
.userInfoEndpoint(userInfoEndpoint ->
userInfoEndpoint
.userAuthoritiesMapper(authoritiesMapper)
)
.loginPage("/login")
.successHandler(new KeycloakVaadinAuthenticationSuccessHandler(profileService))
)
// Configure logout
.logout(logout ->
logout
.logoutSuccessHandler(logoutSuccessHandler())
.logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"))
).sessionManagement(sessionManagement -> {
sessionManagement.sessionConcurrency(concurrency -> {
concurrency.maximumSessions(-1);
concurrency.sessionRegistry(sessionRegistry());
final var expiredStrategy = new UidlExpiredSessionStrategy();
concurrency.expiredSessionStrategy(expiredStrategy);
});
});
setStatelessAuthentication(http, new SecretKeySpec(Base64.getDecoder().decode(jwtAuthSecret), JwsAlgorithms.HS256), "com.example");
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
@Primary
public SpringViewAccessChecker springViewAccessChecker(AccessAnnotationChecker accessAnnotationChecker) {
return new KeycloakSpringViewAccessChecker(accessAnnotationChecker, "/oauth2/authorization/keycloak");
}
private OidcClientInitiatedLogoutSuccessHandler logoutSuccessHandler() {
var logoutSuccessHandler = new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository);
logoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}");
return logoutSuccessHandler;
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
web.ignoring().antMatchers("/session-expired", "/images/*", "/login", "/favicon.ico");
}
@Bean
public PolicyFactory htmlSanitizer() {
return Sanitizers.FORMATTING.and(Sanitizers.BLOCKS).and(Sanitizers.STYLES).and(Sanitizers.LINKS);
}
}
如何正确地将用户重定向到原始页面?
已更新
public class KeycloakVaadinAuthenticationSuccessHandler extends VaadinSavedRequestAwareAuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(KeycloakVaadinAuthenticationSuccessHandler.class);
private final ServiceFacade serviceFacade;
public KeycloakVaadinAuthenticationSuccessHandler(ServiceFacade serviceFacade) {
this.serviceFacade = serviceFacade;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
if (authentication == null || !(authentication instanceof OAuth2AuthenticationToken)) {
String message = String.format("Authentication is null or not an instance of OAuth2AuthenticationToken: %s", authentication);
logger.error(message);
throw new IllegalStateException(message);
}
Collection<VaadinSession> vaadinSessions = VaadinSession.getAllSessions(request.getSession());
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
String keycloakSessionId = (String) token.getPrincipal().getAttributes().get("sid");
serviceFacade.getProfileService().createUserWithProfileIfNotExists((OAuth2AuthenticationToken) authentication, (user, profile, principalUserUuid) -> {
try {
if (CollectionUtils.isNotEmpty(vaadinSessions)) {
for (VaadinSession vaadinSession : vaadinSessions) {
if (vaadinSession.getService() != null) {
vaadinSession.access(() -> {
vaadinSession.setAttribute(UserInfo.SUB_PROPERTY, user.getUuid());
vaadinSession.setAttribute(UserInfo.KEYCLOAK_SESSION_ID, keycloakSessionId);
});
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw new IOException(e);
}
});
super.onAuthenticationSuccess(request, response, authentication);
}
1条答案
按热度按时间gtlvzcf81#
成功处理器负责重定向到原始视图。您用自己的版本覆盖了它,因此它不会立即生效。现在
VaadinWebSecurity
中有一个setOAuth2LoginPage
帮助器,它将设置正确的成功处理器。