From 5e0500933d2f805fe879ced9171c65839c72579b Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Wed, 7 Dec 2022 16:13:57 +0300 Subject: Login: use `Referer` header to redirect after the successful login --- src/main/java/com/juick/config/SecurityConfig.java | 36 +++++++++++++++------ .../java/com/juick/www/SiteAttributesHandler.java | 37 ++++++++++++++++++++++ src/main/java/com/juick/www/VaryHandler.java | 31 ------------------ src/main/java/com/juick/www/controllers/Site.java | 15 ++++----- .../resources/templates/views/login_success.html | 13 -------- .../templates/views/partial/navigation.html | 2 +- .../java/com/juick/server/tests/ServerTests.java | 4 +-- 7 files changed, 72 insertions(+), 66 deletions(-) create mode 100644 src/main/java/com/juick/www/SiteAttributesHandler.java delete mode 100644 src/main/java/com/juick/www/VaryHandler.java delete mode 100644 src/main/resources/templates/views/login_success.html diff --git a/src/main/java/com/juick/config/SecurityConfig.java b/src/main/java/com/juick/config/SecurityConfig.java index f93e12a8..b16dc755 100644 --- a/src/main/java/com/juick/config/SecurityConfig.java +++ b/src/main/java/com/juick/config/SecurityConfig.java @@ -34,7 +34,9 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.RememberMeServices; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; @@ -126,30 +128,45 @@ public class SecurityConfig { BasicAuthenticationFilter.class) .authorizeHttpRequests(requests -> requests .requestMatchers(HttpMethod.OPTIONS).permitAll() - .requestMatchers("/api/", "/api/messages", "/api/avatar", "/api/messages/discussions", - "/api/users", "/api/thread", "/api/tags", "/api/tlgmbtwbhk", "/api/fbwbhk", - "/api/skypebotendpoint", "/api/_fblogin", "/api/_vklogin", "/api/_tglogin", - "/api/_google", "/api/_applelogin", "/api/signup", "/api/inbox", "/api/events", + .requestMatchers("/api/", "/api/messages", "/api/avatar", + "/api/messages/discussions", + "/api/users", "/api/thread", "/api/tags", + "/api/tlgmbtwbhk", "/api/fbwbhk", + "/api/skypebotendpoint", "/api/_fblogin", + "/api/_vklogin", "/api/_tglogin", + "/api/_google", "/api/_applelogin", "/api/signup", + "/api/inbox", "/api/events", "/api/info/**", "/api/nodeinfo/2.0") .permitAll() .anyRequest().hasRole("USER")) .anonymous(anonymous -> anonymous.principal(JuickUser.ANONYMOUS_USER) .authorities(JuickUser.ANONYMOUS_AUTHORITY)) - .httpBasic(httpBasic -> httpBasic.authenticationEntryPoint(juickAuthenticationEntryPoint())) + .httpBasic(httpBasic -> httpBasic + .authenticationEntryPoint(juickAuthenticationEntryPoint())) .cors(cors -> cors.configurationSource(corsConfigurationSource())) - .sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .exceptionHandling(exceptionHandling -> exceptionHandling.authenticationEntryPoint(juickAuthenticationEntryPoint())) + .sessionManagement(sessionManagement -> sessionManagement + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .exceptionHandling(exceptionHandling -> exceptionHandling + .authenticationEntryPoint(juickAuthenticationEntryPoint())) .csrf().disable() .headers().defaultsDisabled().cacheControl(); return http.build(); } + @Bean + public AuthenticationSuccessHandler successHandler() { + SimpleUrlAuthenticationSuccessHandler handler = new SimpleUrlAuthenticationSuccessHandler(); + handler.setUseReferer(true); + return handler; + } + @Bean public SecurityFilterChain wwwChain(HttpSecurity http) throws Exception { http.addFilterBefore(wwwAuthenticationFilter(), BasicAuthenticationFilter.class) .authorizeHttpRequests(authorize -> authorize - .requestMatchers("/settings", "/pm/**", "/**/bl", "/_twitter", "/post", "/post2", + .requestMatchers("/settings", "/pm/**", "/**/bl", "/_twitter", "/post", + "/post2", "/comment") .authenticated() .requestMatchers("/actuator/**").hasRole("ADMIN") @@ -168,10 +185,9 @@ public class SecurityConfig { .logoutSuccessUrl("/") .deleteCookies("hash", COOKIE_NAME)) .formLogin(form -> form.loginPage("/login") - .defaultSuccessUrl("/") - .loginProcessingUrl("/login") .usernameParameter("username") .passwordParameter("password") + .successHandler(successHandler()) .failureUrl("/login?error=1") .permitAll()) .csrf(csrf -> csrf.ignoringRequestMatchers("/settings/unsubscribe", "/h2-console/**")) diff --git a/src/main/java/com/juick/www/SiteAttributesHandler.java b/src/main/java/com/juick/www/SiteAttributesHandler.java new file mode 100644 index 00000000..e06a2070 --- /dev/null +++ b/src/main/java/com/juick/www/SiteAttributesHandler.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008-2020, Juick + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.juick.www; + +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import jakarta.servlet.http.HttpServletResponse; + +@ControllerAdvice +public class SiteAttributesHandler { + @ModelAttribute + public void setVaryResponseHeader(HttpServletResponse response) { + response.setHeader("Vary", "Accept-Language"); + } + @ModelAttribute + public void setReturnPathAttribute(Model model) { + model.addAttribute("retpath", ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString()); + } +} diff --git a/src/main/java/com/juick/www/VaryHandler.java b/src/main/java/com/juick/www/VaryHandler.java deleted file mode 100644 index 6910823d..00000000 --- a/src/main/java/com/juick/www/VaryHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2008-2020, Juick - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package com.juick.www; - -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ModelAttribute; - -import jakarta.servlet.http.HttpServletResponse; - -@ControllerAdvice -public class VaryHandler { - @ModelAttribute - public void setVaryResponseHeader(HttpServletResponse response) { - response.setHeader("Vary", "Accept-Language"); - } -} diff --git a/src/main/java/com/juick/www/controllers/Site.java b/src/main/java/com/juick/www/controllers/Site.java index a0b8c5b0..aa6d574d 100644 --- a/src/main/java/com/juick/www/controllers/Site.java +++ b/src/main/java/com/juick/www/controllers/Site.java @@ -46,6 +46,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import javax.inject.Inject; import java.net.URLEncoder; @@ -96,10 +97,12 @@ public class Site { } @GetMapping("/login") - public String getloginForm(@Visitor User visitor, HttpSession session, - @RequestParam(required = false, defaultValue = "true") boolean redirect, ModelMap model) { + public String getloginForm(@Visitor User visitor, + @RequestParam(name = "retpath", required = false, defaultValue = "/") String retPath, + HttpSession session, + ModelMap model) { if (!visitor.isAnonymous()) { - return redirect ? "redirect:/" : "redirect:/login/success"; + return String.format("redirect:%s", retPath); } model.addAttribute("visitor", visitor); model.addAttribute("tags", tagService.getPopularTags()); @@ -119,12 +122,6 @@ public class Site { return "views/login"; } - @GetMapping("/login/success") - public String getSuccessLogin(@Visitor User visitor, ModelMap model) { - model.addAttribute("hash", userService.getHashByUID(visitor.getUid())); - return "views/login_success"; - } - @GetMapping("/") protected String doGet(@Visitor User visitor, Locale locale, @RequestParam(required = false) String tag, @RequestParam(name = "show", required = false) String paramShow, diff --git a/src/main/resources/templates/views/login_success.html b/src/main/resources/templates/views/login_success.html deleted file mode 100644 index ee71f12f..00000000 --- a/src/main/resources/templates/views/login_success.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Blank window - - - - - diff --git a/src/main/resources/templates/views/partial/navigation.html b/src/main/resources/templates/views/partial/navigation.html index 184c8f2b..159c3d21 100644 --- a/src/main/resources/templates/views/partial/navigation.html +++ b/src/main/resources/templates/views/partial/navigation.html @@ -33,7 +33,7 @@ {{ i18n("messages","link.postMessage") }} {% else %} - diff --git a/src/test/java/com/juick/server/tests/ServerTests.java b/src/test/java/com/juick/server/tests/ServerTests.java index b40cbc04..367b8e47 100644 --- a/src/test/java/com/juick/server/tests/ServerTests.java +++ b/src/test/java/com/juick/server/tests/ServerTests.java @@ -1959,9 +1959,9 @@ public class ServerTests { Cookie rememberMeFromForm = formLoginResult.getResponse().getCookie("juick-remember-me"); mockMvc.perform(get("/login").cookie(rememberMeFromForm)).andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("/")); - mockMvc.perform(get("/login?redirect=false").cookie(rememberMeFromForm)) + mockMvc.perform(get("/login?retpath=http://localhost:8080/logged_in").cookie(rememberMeFromForm)) .andExpect(status().is3xxRedirection()) - .andExpect(redirectedUrl("/login/success")); + .andExpect(redirectedUrl("http://localhost:8080/logged_in")); } @Test -- cgit v1.2.3