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

7vhp5slm  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(194)

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

gtlvzcf81#

成功处理器负责重定向到原始视图。您用自己的版本覆盖了它,因此它不会立即生效。现在VaadinWebSecurity中有一个setOAuth2LoginPage帮助器,它将设置正确的成功处理器。

相关问题