我正在扩展UsernamePasswordAuthenticationFilter
,以便我可以添加自定义字段以将其保存到会话中。
public class AuthFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
//String dbValue = request.getParameter("dbParam");
//request.getSession().setAttribute("dbValue", dbValue);
System.out.println("attempting to authentificate");
while (request.getAttributeNames().hasMoreElements()) {
String e = (String) request.getAttributeNames().nextElement();
System.out.println("param name : " + e + " and param value : " + request.getAttribute(e));
}
return super.attemptAuthentication(request, response);
}
}
我的WebSecurityConfig
@Configuration
@EnableWebMvcSecurity
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public AuthFilter customUsernamePasswordAuthenticationFilter()
throws Exception {
AuthFilter customUsernamePasswordAuthenticationFilter = new AuthFilter();
customUsernamePasswordAuthenticationFilter
.setAuthenticationManager(authenticationManagerBean());
return customUsernamePasswordAuthenticationFilter;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(customUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
http.exceptionHandling().accessDeniedPage("/403").and()
.authorizeRequests().antMatchers("/login", "/public/**").permitAll()
.antMatchers("/users/**").hasAuthority("ADMIN")
.anyRequest()
.authenticated().and().formLogin().loginPage("/login")
.defaultSuccessUrl("/index").permitAll().and().logout()
.permitAll();
http.sessionManagement().maximumSessions(1)
.expiredUrl("/login?expired").and()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.eraseCredentials(false)
.userDetailsService(userDetailsService);
}
映射过滤器:' customUsernamePasswordAuthenticationFilter'致:[/ *]
所以我确定已经正确添加了过滤器,但是我永远无法打印出内部的内容,因此在验证过程中不会调用它。
我使用的是Thymeleaf,没有xml配置。
作为@M。 Deinum建议,
我将UsernamePasswordAuthenticationFilter
改为AbstractAuthenticationProcessingFilter
,称为super(new AntPathRequestMatcher("/login","POST"));
将addFilterAfter
更改为addFilterBefore
,以及一些代码,并且有效!
答案 0 :(得分:8)
假设您使用的是最新的Spring Boot(1.2.3),那么您使用的是Spring Security 3.2.7。此版本将UsernamePasswordAuthenticationFilter
映射到/j_spring_security_check
。但是,使用基于java的配置时,这将更改为/login
。
您仍然会映射到旧网址。要修复此扩展AbstractAuthenticationProcessingFilter
,请添加一个默认的no-args构造函数,该构造函数调用带有RequestMatcher
的超级构造函数。这样做的缺点是,如果您仍然需要(或想要扩展)UsernamePasswordAuthenticationFilter
的功能,则必须复制它。
public AuthFilter() {
super(new AntPathRequestMatcher("/login","POST"));
}
另一种解决方案是继续扩展UsernamePasswordAuthenticationFilter
并从那里调用setRequiresAuthenticationRequestMatcher
。
public AuthFilter() {
super();
setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login","POST"));
}
或者您从工厂方法调用该方法。
@Bean
public AuthFilter customUsernamePasswordAuthenticationFilter()
throws Exception {
AuthFilter customUsernamePasswordAuthenticationFilter = new AuthFilter();
customUsernamePasswordAuthenticationFilter
.setAuthenticationManager(authenticationManagerBean());
customUsernamePasswordAuthenticationFilter
.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login","POST"));
return customUsernamePasswordAuthenticationFilter;
}
您的配置还有另一个问题,您的过滤器将永远不会被执行,因为它在默认UsernamePasswordAuthenticationFilter
之后执行,并且身份验证已经发生,您的过滤器将永远不会执行。确保它在默认过滤器之前执行。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(customUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
...
}
答案 1 :(得分:1)
为了使您的自定义UsernamePasswordAuthenticationFilter实现起作用,请将.loginProcessingUrl(“ / dologin”)添加到您的HttpSecurity中 WebSecurityConfig,这里的“ / dologin”是html表单元素的动作属性值:
@Override
//@Order(Ordered.HIGHEST_PRECEDENCE)
public void configure(HttpSecurity http) throws Exception { // @formatter:off
http
...
...
.formLogin().loginPage("/login")
--> .loginProcessingUrl("/dologin") <-- add here
...
--> .addFilterBefore(new AuthFilter(authenticationManagerBean()),UsernamePasswordAuthenticationFilter.class)
}
下一步是提供自定义的UsernamePasswordAuthenticationFilter实现:
public class AuthFilter extends UsernamePasswordAuthenticationFilter {
AuthenticationManager authenticationManager;
private boolean continueChainBeforeSuccessfulAuthentication = false;
public AuthFilter( AuthenticationManager authenticationManager){
this.authenticationManager = authenticationManager;
//idk why I have to do this, otherwise it's null
super.setAuthenticationManager(authenticationManager);
}
public AuthFilter() {}
private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy();
//path to which this filter will intercept
RequestMatcher customFilterUrl = new AntPathRequestMatcher("/dologin"); <--
//dofilter method is copied from AbstractAuthenticationProcessingFilter
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
//if no match then go to next filter
if (!customFilterUrl.matches(request)) {
chain.doFilter(request, response);
} else {
Authentication authResult;
try {
authResult = this.attemptAuthentication(request, response);
if (authResult == null) {
return;
}
this.sessionStrategy.onAuthentication(authResult, request, response);
} catch (InternalAuthenticationServiceException var8) {
this.logger.error("An internal error occurred while trying to authenticate the user.", var8);
this.unsuccessfulAuthentication(request, response, var8);
return;
} catch (AuthenticationException var9) {
this.unsuccessfulAuthentication(request, response, var9);
return;
}
if (this.continueChainBeforeSuccessfulAuthentication) {
chain.doFilter(request, response);
}
successfulAuthentication(request, response, chain, authResult);
}
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response)
throws AuthenticationException {
System.out.println("Your prints"); <--
return super.attemptAuthentication(request,response);
}
}