引言:在使用springSecurity后,我们知道有一个默认的接口"/login"可以实现认证功能(即通过用户名和密码登录),在登录时通常会看到"Bad credentials",那么是什么地方抛出的呢?它底层是如何实现的呢? 陷入沉思…(手动点烟!)
SpringSecurity认证源码分析
我们知道SpringSecurity的本质是一个过滤器链,即一个一个的过滤器,至于在springBoot启动的时候是如何加载的还没去研究.我们只需要知道其中的一个过滤器是UsernamePasswordAuthenticationFilter,那么认证就要从这个过滤器说起.
首先,我们看到它集成了一个过滤器叫AbstractAuthenticationProcessingFilter既然它是父类,那么就是先执行父类中的方法,如果父类里有没有实现的方法才会是去子类中实现
AbstractAuthenticationProcessingFilter.java
这个类中有三个方法:
doFilter():这个就不用说了
successfulAuthentication():认证成功后逻辑
unsuccessfulAuthentication():认证失败之后逻辑
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (!requiresAuthentication(request, response)) {
chain.doFilter(request, response);
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Request is to process authentication");
}
Authentication authResult;
try {
/**
*认证:在其子类中实现
这里是调用了attemptAuthentication(request, response)方法,
它在此类中并没实现要去它的子类中实现
*/
authResult = attemptAuthentication(request, response);
if (authResult == null) {
return;
}
//放到缓存中
sessionStrategy.onAuthentication(authResult, request, response);
}
catch (InternalAuthenticationServiceException failed) {
logger.error(
"An internal error occurred while trying to authenticate the user.",
failed);
//认证失败的方法
unsuccessfulAuthentication(request, response, failed);
return;
}
catch (AuthenticationException failed) {
//认证成功的方法
unsuccessfulAuthentication(request, response, failed);
return;
}
if (continueChainBeforeSuccessfulAuthentication) {
chain.doFilter(request, response);
}
successfulAuthentication(request, response, chain, authResult);
}
通过观察此类可以发现其认证的真正实现是在它的子类UsernamePasswordAuthenticationFilter中实现的.先看一下这个类.
UsernamePasswordAuthenticationFilter.java
主要是它实现的 attemptAuthentication(request, response) 这个方法.
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = <