警告 :使用参数来确定要重定向到的位置可以将应用程序打开到“
打开重定向漏洞”为止。基于用户输入执行重定向时要非常小心。
ContinueEntryPoint
您的第一步是创建一个
AuthenticationEntryPoint,负责在显示登录表单时在URL中包含一个参数以继续在URL中。在这个例子中,我们将使用参数名称continue。
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;import org.springframework.security.web.util.UrlUtils;import org.springframework.web.util.UriComponentsBuilder;public class ContinueEntryPoint extends LoginUrlAuthenticationEntryPoint { public ContinueEntryPoint(String loginFormUrl) { super(loginFormUrl); } @Override protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) { String continueParamValue = UrlUtils.buildRequestUrl(request); String redirect = super.determineUrlToUseForThisRequest(request, response, exception); return UriComponentsBuilder.fromPath(redirect).queryParam("continue", continueParamValue).toUriString(); }}Web安全配置
下一步将包括使用ContinueEntryPoint的安全性配置。例如:
import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@EnableWebSecuritypublic class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .exceptionHandling() .authenticationEntryPoint(new ContinueEntryPoint("/login")) .and() .authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .formLogin(); }}LoginController
最后,如果用户已经通过身份验证,则应该创建一个LoginController重定向到该参数。例如:
import javax.validation.constraints.Pattern;import org.hibernate.validator.constraints.NotBlank;public class RedirectModel { @Pattern(regexp="^/([^/].*)?$") @NotBlank private String continueUrl; public void setContinue(String continueUrl) { this.continueUrl = continueUrl; } public String getContinue() { return continueUrl; }}@Controllerpublic class LoginController { @RequestMapping("/login") public String login(Principal principal, @Valid @ModelAttribute RedirectModel model, BindingResult result) { if (!result.hasErrors() && principal != null) { // do not redirect for absolute URLs (i.e. https://evil.com) // do not redirect if we are not authenticated return "redirect:" + model.getContinue(); } return "login"; }}完整样本
您可以在sow.34087954-continue-on-login分支的rwinch / spring-security-
sample中的github中找到完整的示例。如果您不想使用git,则可以轻松下载它。



