应用程序记录所有请求的url
。这意味着,使用url参数进行身份验证至关重要,因为这会导致日志中充满对(login=abc&password=123)
的情况。出于这个原因,我已将spring-security
配置为从request-body
读取参数。这是通过将以下行添加到request-header
:
'Content-Type': 'application/x-www-form-urlencoded'
身体将是:
{'login':'admin', 'password':'password'}
没关系,但QA强迫我通过url参数禁用身份验证的可能性。目前,对以下URL的POST也将进行身份验证:
https://example.com/foo?login=admin&password=password
有没有人知道禁用此选项的技巧?最好带注释。
由于评论我决定在我的问题中添加更多细节。我的spring-security配置了WebSecurityConfigurerAdapter
。我有
http.usernameParameter("login")
.passwordParameter("password")
(...)
这使Spring
在 - 参数和正文中搜索登录数据。我希望禁用在网址中搜索这些参数。
答案 0 :(得分:15)
这使得Spring在参数和正文中搜索登录数据。我希望禁用在网址中搜索这些参数。
我认为这是不可能的,因为Spring没有实现这种行为而不是JavaEE本身。
HttpServletRequest.getParameter doc声明:
以String形式返回请求参数的值,如果参数不存在,则返回null。请求参数是随请求一起发送的额外信息。对于HTTP servlet,参数包含在查询字符串或发布的表单数据中。
但您可以尝试使用看起来像这样的过滤器来改变它:
public class DisableGetAuthFiler extends OncePerRequestFilter {
...
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(
new HttpServletRequestWrapper(request) {
@Override
public String getParameter(String name) {
if (("login".equals(name) && getQueryString().contains("login"))
|| ("password".equals(name) && getQueryString().contains("password"))) {
return null;
} else {
return super.getParameter(name);
}
}
},
response
);
}
}
编辑 Haim Raman建议使用现有过滤器而不是引入新过滤器的另一个solution。只有我建议覆盖obtainUsername()
和obtainPassword()
而不是attemptAuthentication()
。
答案 1 :(得分:7)
我想建议一个基于spring-security rater的替代方案,然后根据chimmi建议的解决方法。
此答案提供xenteros对bres26答案建议的问题的解决方案
覆盖现有的UsernamePasswordAuthenticationFilter实现
public class ImprovedUsernamePasswordAuthenticationFilter
extends UsernamePasswordAuthenticationFilter {
@Override
protected String obtainUsername(HttpServletRequest request) {
final String usernameParameter = getUsernameParameter();
validateQueryParameter(request, usernameParameter);
return super.obtainUsername(request);
}
@Override
protected String obtainPassword(HttpServletRequest request) {
final String passwordParameter = getPasswordParameter();
validateQueryParameter(request, passwordParameter);
return super.obtainPassword(request);
}
private void validateQueryParameter(HttpServletRequest request, String parameter) {
final String queryString = request.getQueryString();
if (!StringUtils.isEmpty(queryString)) {
if (queryString.contains(parameter))
throw new AuthenticationServiceException("Query parameters for login are a prohibit, use message body only!");
}
}
}
您需要将现有的实现替换为现有的实现(请参阅文档here)
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home","/login").permitAll()
.anyRequest().authenticated()
.and()
.logout()
.permitAll()
.and()
//Replace FORM_LOGIN_FILTER with your own custom implementation
.addFilterAt(improvedUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
.and()
//disable csrf to allow easy testing
.csrf().disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
public UsernamePasswordAuthenticationFilter improvedUsernamePasswordAuthenticationFilter() throws Exception {
UsernamePasswordAuthenticationFilter authFilter = new ImprovedUsernamePasswordAuthenticationFilter();
authFilter.setRequiresAuthenticationRequestMatcher(
new AntPathRequestMatcher("/login", "POST")
);
authFilter
.setAuthenticationManager(authenticationManager());
authFilter
.setAuthenticationSuccessHandler(
new SavedRequestAwareAuthenticationSuccessHandler()
);
authFilter
.setAuthenticationFailureHandler(
new SimpleUrlAuthenticationFailureHandler("/login?error")
);
return authFilter;
}
}
优势:它基于弹簧安全性,并且灵活变化 缺点:不幸的是我发现Spring Java Config很难设置和阅读
编辑:我接受chimmi评论并覆盖了getsUsername和obtainPassword
您可以在github中找到源代码。
答案 2 :(得分:6)
就我所知和直觉而言,就像詹提到的那样,适当的解决方案是使用注释@RequestMapping(value="/login", method="RequestMethod.POST")
。然后,无论用户使用URL传递什么参数,URL和URI都将始终默认为/ login。这就是记录器将记录的内容。不是用户名和密码对,而是"http://localhost:8080/login"
或任何端口。
答案 3 :(得分:6)
您可以通过修改UsernamePasswordAuthenticationFilter
的{{1}}来实现此目的。例如:
RequestMatcher
注意:以下要求不会阻止发出GET请求(从而泄露凭据)。 UI确实不会发生这种情况。
没关系,但QA迫使我禁用它的可能性 通过url paramters进行身份验证。