在使用Spring Security框架过程当中,常常会有这样的需求,即在登陆验证时,附带增长额外的数据,如验证码、用户类型等。下面将介绍如何实现。css
注:个人工程是在Spring Boot框架基础上的,使用xml方式配置的话请读者自行研究吧。html
该类提供了获取用户登陆时携带的额外信息的功能,默认实现WebAuthenticationDetails提供了remoteAddress与sessionId信息。开发者能够经过Authentication的getDetails()获取WebAuthenticationDetails。咱们编写自定义类CustomWebAuthenticationDetails继承自WebAuthenticationDetails,添加咱们关心的数据(如下是一个token字段)。java
package com.cgs.courses.service; import javax.servlet.http.HttpServletRequest; import org.springframework.security.web.authentication.WebAuthenticationDetails; public class CustomWebAuthenticationDetails extends WebAuthenticationDetails { /** * */ private static final long serialVersionUID = 6975601077710753878L; private final String token; public CustomWebAuthenticationDetails(HttpServletRequest request) { super(request); token = request.getParameter("token"); } public String getToken() { return token; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(super.toString()).append("; Token: ").append(this.getToken()); return sb.toString(); } }
注:在登陆页面,可将token字段放在form表单中,也能够直接加在url的参数中,进而把额外数据发送给后台。web
该接口用于在Spring Security登陆过程当中对用户的登陆信息的详细信息进行填充,默认实现是WebAuthenticationDetailsSource,生成上面的默认实现WebAuthenticationDetails。咱们编写类实现AuthenticationDetailsSource,用于生成上面自定义的CustomWebAuthenticationDetails。spring
package com.cgs.courses.service;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
@Component
public class CustomAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
@Override
public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
return new CustomWebAuthenticationDetails(context);
}
}
只要看这一句.formLogin().authenticationDetailsSource(authenticationDetailsSource)session
@Autowired private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource; protected void configure(HttpSecurity http) throws Exception { http .headers() .cacheControl() .contentTypeOptions() .httpStrictTransportSecurity() .xssProtection() .and() .authorizeRequests() .antMatchers( "/css/**", "/js/**") .permitAll() .antMatchers("/**") .authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .defaultSuccessUrl("/todo.html", true) .authenticationDetailsSource(authenticationDetailsSource) .and() .logout() .logoutUrl("/logout") .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/login") .and() .csrf().disable(); }
AuthenticationProvider提供登陆验证处理逻辑,咱们实现该接口编写本身的验证逻辑。app
package com.cgs.courses.service; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.stereotype.Component; @Component public class CustomAuthenticationProvider implements AuthenticationProvider { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { CustomWebAuthenticationDetails details = (CustomWebAuthenticationDetails) authentication.getDetails(); // 如上面的介绍,这里经过authentication.getDetails()获取详细信息 // System.out.println(details); details.getRemoteAddress(); details.getSessionId(); details.getToken();
// 下面是验证逻辑,验证经过则返回UsernamePasswordAuthenticationToken,
// 不然,可直接抛出错误(AuthenticationException的子类,在登陆验证不经过重定向至登陆页时可经过session.SPRING_SECURITY_LAST_EXCEPTION.message获取具体错误提示信息)
if (验证经过) {
return UsernamePasswordAuthenticationToken(省略参数);
} else {
throw new AuthenticationException的子类("你要显示的错误信息")
} } @Override public boolean supports(Class<?> authentication) { return authentication.equals(UsernamePasswordAuthenticationToken.class); } }
@Autowired
private AuthenticationProvider authenticationProvider;
@Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authenticationProvider); }