目录
一、从过滤器链开始
当我们执行认证逻辑,在获取用户信息时,可打一个断点,跟踪程序的调用链

在程序的调用链中,找到一个 StandardWrapperValve 的记录,StandardWrapperValve.class 类位于 tomcat 核心包中,跟踪到这个调用位置(StandardWrapperValve#invoke),可以看到过滤器链的调用

二、获取用户信息
在调用链的一系列过滤器中,找到 UsernamePasswordAuthenticationFilter.calss(用户名和密码认证过滤器)

用户名和密码认证过滤器继承了 AbstractAuthenticationProcessingFilter.calss,该过滤器的 #doFilter 方法中,调用了用户名和密码认证过滤器中用户认证的逻辑
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 {
// 调用认证逻辑-> 返回认证结果
authResult = attemptAuthentication(request, response);
if (authResult == null) {
// return immediately as subclass has indicated that it hasn't completed
// authentication
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) {
// 扩展点 Authentication failed 认证失败
unsuccessfulAuthentication(request, response, failed);
return;
}
// Authentication success 认证成功
if (continueChainBeforeSuccessfulAuthentication) {
chain.doFilter(request, response);
}
// 扩展点 -> AuthenticationSuccessHandler
successfulAuthentication(request, response, chain, authResult);
}
调用 attemptAuthentication(request, response) 抽象方法

UsernamePasswordAuthenticationFilter#attemptAuthentication 实现了该抽象方法
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
// 1-必须为 post 方法
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
// 2-解析用户名和密码 -> 固定解析参数名称 'username','password'
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
// 3-封装到认证的token,此时认证状态为 false -> setAuthenticated(false);
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
// 4-调用认证管理器进行认证 -> 认证核心逻辑
return this.getAuthenticationManager().authenticate(authRequest);
}
方法 this.getAuthenticationManager().authenticate(authRequest); 调用认证管理器的具体实现进行权限验证
具体认证管理器的实现逻辑为 ProviderManager.class#authenticate
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
AuthenticationException parentException = null;
Authentication result = null;
Authentication parentResult = null;
boolean debug = logger.isDebugEnabled();
// providers 列表循环
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {

5万+

被折叠的 条评论
为什么被折叠?



