spring-security - Vaadin 23 Spring Security with Keycloak - 登录后将用户重定向到正确的页面

标签 spring-security vaadin keycloak vaadin-flow vaadin23

我使用 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);
    }

最佳答案

成功处理程序负责重定向到原始 View 。您将使用自己的版本覆盖它,因此它无法开箱即用。现在,VaadinWebSecurity 中有一个 setOAuth2LoginPage 帮助程序,它将设置正确的成功处理程序。

关于spring-security - Vaadin 23 Spring Security with Keycloak - 登录后将用户重定向到正确的页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74280877/

相关文章:

java - Spring Security + Google App Engine + UserService : What is the correct way to logout?

spring-security - Spring Security Webflux/响应式(Reactive)异常处理

jakarta-ee - 如何将动态生成的 SVG 包含到 Vaadin UI?

java - 从 keycloak 进行身份验证时如何获取用户角色和客户端角色

regex - Perl 正则表达式 |如何从文件中排除单词

post - 在带有Java Config的Spring-Security中,为什么httpBasic POST想要csrf token ?

java - 右对齐文本字段中的文本 - vaadin

Vaadin - 从多个对象到 Grid 的数据

kubernetes - 如何使用自定义配置在 kubernetes 上部署 keycloak?

java - 在 Spring 中使用 Cookie 对 Restful 服务进行身份验证