java Spring Security - 在重定向到登录时保留 URL 参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14282569/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Security - Retaining URL parameters on redirect to login
提问by kabal
ok.
行。
lets say I have a secure url pattern
假设我有一个安全的 url 模式
/secure/link-profile
optionally, there can be url paramaters appended.
可选地,可以附加 url 参数。
/secure/link-profile?firstName=Bob&secondName=Smith&membershipNumber=1234
how can I make it so that those url params are carried over to the login page?
我怎样才能让这些 url 参数被带到登录页面?
/login?firstName=Bob&secondName=Smith&membershipNumber=1234
the basic premise is that we offer rewards integration with a 3rd party, who will send their users to us. They will be taken to a page to link their 3rd party account/profile with their/our website user. If however, they dont have an existing account with us, then on the login page, they will go to the signup page, and we would then like to prepopulate some of their details that the 3rd party has passed on to us.
基本前提是我们提供与第三方的奖励集成,第三方会将他们的用户发送给我们。他们将被带到一个页面,将他们的第 3 方帐户/个人资料与他们/我们的网站用户相关联。但是,如果他们没有我们的现有帐户,则在登录页面上,他们将转到注册页面,然后我们希望预先填充第 3 方传递给我们的一些详细信息。
thanks in advance
提前致谢
spring security 2.0.7.RELEASE spring framework 3.1.1.RELEASE
弹簧安全 2.0.7.RELEASE 弹簧框架 3.1.1.RELEASE
采纳答案by zagyi
See the method buildRedirectUrlToLoginPage(HttpServletRequest request, ...)
in LoginUrlAuthenticationEntryPoint
.
请参阅法buildRedirectUrlToLoginPage(HttpServletRequest request, ...)
在LoginUrlAuthenticationEntryPoint
。
If I understood correctly what you want to achieve, I think it should be enough to override this method in a sublclass, copy the original method, but additionally call urlBuilder.setQuery(request.getQueryString())
when it builds the url.
如果我正确理解您想要实现的目标,我认为在子类中覆盖此方法应该就足够了,复制原始方法,但urlBuilder.setQuery(request.getQueryString())
在构建 url 时另外调用。
Then you only need to configure the ExceptionTranslationFilter
with this customized entry point.
然后你只需要ExceptionTranslationFilter
使用这个自定义的入口点来配置。
回答by kabal
as per @zagyi's response I just overrode a method in my existing extension of AuthenticationProcessingFilterEntryPoint
根据@zagyi 的回复,我只是在我现有的扩展中覆盖了一个方法 AuthenticationProcessingFilterEntryPoint
the method to override is protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception)
which is called by buildRedirectUrlToLoginPage(..
要覆盖的方法protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception)
是由调用buildRedirectUrlToLoginPage(..
@Override
protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) {
String url = super.determineUrlToUseForThisRequest(request, response, exception);
return url + "?" + request.getQueryString();
}
obviously that could be improved to also use a builder of sorts, catering for an existing query string on the url, but at this time I know my login url is always /login/
, so this is fine for my purposes
显然,这可以改进为也使用各种构建器,以满足 url 上现有的查询字符串,但此时我知道我的登录 url 总是/login/
,所以这对我的目的来说很好
回答by San
A different articleexplains how overriding does not work. I needed to override commence. This may perhaps be a new thing that was introduced in later versions of spring security.
另一篇文章解释了覆盖如何不起作用。我需要覆盖开始。这可能是spring security以后版本引入的新东西。
public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(final HttpSecurity httpSecurity) throws Exception {
httpSecurity.
formLogin().loginPage("/signIn").permitAll().
and().
authorizeRequests().
antMatchers(managementContextPath + "/**").permitAll().
anyRequest().authenticated().withObjectPostProcessor(objectPostProcessor).
and().
csrf().disable().
contentTypeOptions().
xssProtection().
cacheControl().
httpStrictTransportSecurity().
and().
requestCache().requestCache(new RedisRequestCache(savedRequestRedisTemplate())).
and().
sessionManagement().sessionAuthenticationStrategy(sessionAuthenticationStrategy).
and().
exceptionHandling().authenticationEntryPoint(new AuthenticationProcessingFilterEntryPoint("/signIn"));
}
}
public class AuthenticationProcessingFilterEntryPoint extends LoginUrlAuthenticationEntryPoint { public AuthenticationProcessingFilterEntryPoint(String loginFormUrl) { super(loginFormUrl); } @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); redirectStrategy.sendRedirect(request, response, getLoginFormUrl() + "?" + request.getQueryString()); } }
Rizier123, thanks again for your pointers.
Rizier123,再次感谢您的指点。
回答by San
Hi kabal-
嗨卡巴尔-
I have very similar requirements, and I followed yours and zagyi's and lion'spost, but I still seem to loose the original request parameter on /login page.
我有非常类似的要求,我也跟着你的,zagyi的和狮子的职位,但我似乎仍然失去原来的请求参数上/登录页面。
Here's what I have:
这是我所拥有的:
public class AuthenticationProcessingFilterEntryPoint extends LoginUrlAuthenticationEntryPoint {
@Override
protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) {
String url = super.determineUrlToUseForThisRequest(request, response, exception);
return url + "?" + request.getQueryString();
}
}
protected void configure(final HttpSecurity httpSecurity) throws Exception {
httpSecurity.
formLogin().loginPage("/signIn").permitAll().
and().
authorizeRequests().
antMatchers(managementContextPath + "/**").permitAll().
anyRequest().authenticated().withObjectPostProcessor(objectPostProcessor).
and().
csrf().disable().
contentTypeOptions().
xssProtection().
cacheControl().
httpStrictTransportSecurity().
and().
requestCache().requestCache(new RedisRequestCache(savedRequestRedisTemplate())).
and().
sessionManagement().sessionAuthenticationStrategy(sessionAuthenticationStrategy).
and().
addFilter(new ExceptionTranslationFilter(new AuthenticationProcessingFilterEntryPoint()));
}
I can see that AuthenticationProcessingFilterEntryPoint is deployed, but it does not hit a breakpoint there.
我可以看到 AuthenticationProcessingFilterEntryPoint 已部署,但它没有在那里遇到断点。
Based on the documentation, it appears that this will kick in only when there is AuthenticationException or AccessDeniedException. In the configuration above, I am not sure if the spring internally throws such exception when such happens.
根据文档,这似乎只有在出现 AuthenticationException 或 AccessDeniedException 时才会启动。在上面的配置中,我不确定发生这种情况时 spring 是否会在内部抛出此类异常。
Additionally, I'd like to to preserve the query parameter on the landing page regardless authentication succeeds or not.
此外,无论身份验证成功与否,我都想在登录页面上保留查询参数。
I did add success and failure handler, but none would kick into action.
我确实添加了成功和失败处理程序,但没有人会开始行动。
protected void configure(final HttpSecurity httpSecurity) throws Exception {
httpSecurity.
formLogin().
successHandler(new PropogateQueryStringAuthenticationSuccessHandlerImpl()).
failureHandler(new SimpleUrlAuthenticationFailureHandlerImpl(new QueryStringPropagateRedirectStrategy())).
and().
authorizeRequests().
antMatchers(managementContextPath + "/**").permitAll().
anyRequest().authenticated().withObjectPostProcessor(objectPostProcessor).
and().
csrf().disable().
contentTypeOptions().
xssProtection().
cacheControl().
httpStrictTransportSecurity().
and().
requestCache().requestCache(new RedisRequestCache(savedRequestRedisTemplate())).
and().
sessionManagement().sessionAuthenticationStrategy(sessionAuthenticationStrategy);
}
I am using spring-security 3.2.4.RELEASE on spring boot 1.1.6.RELEASE(which in turn uses Spring framework 4.0.7.RELEASE)
我在 spring boot 1.1.6.RELEASE 上使用 spring-security 3.2.4.RELEASE(反过来使用 Spring 框架 4.0.7.RELEASE)
Thanks, San
谢谢,桑