SpringSecurity study notes two

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/zyxwvuuvwxyz/article/details/102747149

SpringSecurity certification success, failure analysis principles processor

First of all you need to know it is that, SpringSecurity default successes, failures processor SavedRequestAwareAuthenticationSuccessHandlerand SimpleUrlAuthenticationFailureHandler; under normal circumstances, a resource request, entering into SpringSecurity authentication, the authentication is successful will jump to be requested resource

SavedRequestAwareAuthenticationSuccessHandler source code analysis

Authentication is successful Processor process: when a user requests an interface will be blocked SpringSecurity. When the user authentication is successful, it will jump to the interface before a user wants to request there

Question: how to know the user's request it?
SavedRequest getRequest(HttpServletRequest request, HttpServletResponse response). This method can be cached to the user's request.

Assuming that the user has been successfully authenticated, the authentication is successful then the call flow on the processor are:
AbstractAuthenticationProcessingFilter#successfulAuthentication> AuthenticationSuccessHandler#onAuthenticationSuccess>SavedRequestAwareAuthenticationSuccessHandler#onAuthenticationSuccess

SavedRequestAwareAuthenticationSuccessHandler

@Override
//这里是重写了该方法,与父类里的实现不一样了
	public void onAuthenticationSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication authentication)
			throws ServletException, IOException {
			//将用户的原始请求缓存住 放到SavedRequest里
		SavedRequest savedRequest = requestCache.getRequest(request, response);

		if (savedRequest == null) {
			super.onAuthenticationSuccess(request, response, authentication);

			return;
		}
		String targetUrlParameter = getTargetUrlParameter();
		if (isAlwaysUseDefaultTargetUrl()
				|| (targetUrlParameter != null && StringUtils.hasText(request
						.getParameter(targetUrlParameter)))) {
			requestCache.removeRequest(request, response);
			super.onAuthenticationSuccess(request, response, authentication);

			return;
		}
//删除可能已存储在服务器中的与身份验证有关的临时数据
		clearAuthenticationAttributes(request);

		String targetUrl = savedRequest.getRedirectUrl();
		logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
		//跳转到指定的原用户请求路径
		getRedirectStrategy().sendRedirect(request, response, targetUrl);
	}

Here getRedirectStrategy () is DefaultRedirectStrategy.

DefaultRedirectStrategy

public void sendRedirect(HttpServletRequest request, HttpServletResponse response,
			String url) throws IOException {
			//处理url
		String redirectUrl = calculateRedirectUrl(request.getContextPath(), url);
		redirectUrl = response.encodeRedirectURL(redirectUrl);

		if (logger.isDebugEnabled()) {
			logger.debug("Redirecting to '" + redirectUrl + "'");
		}
		//这里执行跳转操作
		response.sendRedirect(redirectUrl);
	}

SavedRequestAwareAuthenticationSuccessHandler source code analysis

When the onAuthenticationFailuremethod is invoked, AuthenticationFailureHandlerbased on defaultFailureUrlthe jump path. If defaultFailureUrlnot set, it will send 401 error code and the AuthenticationExceptionerror message related to the client.
If the useForwardproperty is set, then RequestDispatcher.forwareit will be redirected to the destination rather than jump.

public void onAuthenticationFailure(HttpServletRequest request,
			HttpServletResponse response, AuthenticationException exception)
			throws IOException, ServletException {
		//如果默认的错误跳转路径为空
		if (defaultFailureUrl == null) {
			logger.debug("No failure URL set, sending 401 Unauthorized error");

			response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
					"Authentication Failed: " + exception.getMessage());
		}
		else {
			//保存异常信息
			saveException(request, exception);
			//如果forwardToDestination属性值为true
			if (forwardToDestination) {
				logger.debug("Forwarding to " + defaultFailureUrl);

				request.getRequestDispatcher(defaultFailureUrl)
						.forward(request, response);
			}
			else {
				logger.debug("Redirecting to " + defaultFailureUrl);
				redirectStrategy.sendRedirect(request, response, defaultFailureUrl);
			}
		}
	}
	
	//根据forwardToDestination的值 选择性的将错误信息 保存在request[重定向与原请求公用一个request域]中或session中。
	protected final void saveException(HttpServletRequest request,
			AuthenticationException exception) {
		if (forwardToDestination) {
			request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
		}
		else {
			HttpSession session = request.getSession(false);

			if (session != null || allowSessionCreation) {
				request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION,
						exception);
			}
		}
	}

Custom success, failure processor

Success processor

@Component
@Log
public class MyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private SecurityProperties securityProperties;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        log.info("登录成功处理器");
        	//这种方式 即调用父类的方法 是成功之后跳转到指定url
          //  super.onAuthenticationSuccess(request, response, authentication);
       
       //下面这种方式 是将认证成功的用户信息打印到控制台
          response.setContentType("application/json;charset=UTF-8");
          response.getWriter().write(objectMapper.writeValueAsString(authentication));
        }
    }
}

Processor failure

@Component
@Log
public class MyAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    //SpringMVC加载JSON解析工具时 注入的 可以直接用
    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private SecurityProperties securityProperties;

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        log.info("登录失败处理器");
       //这种方式 即调用父类的方法 是失败之后跳转
           // super.onAuthenticationFailure(request, response, exception);
         //下面这种方式 是将认证失败的错误信息打印到控制台
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(objectMapper.writeValueAsString(exception));
        }
    }
}

Custom authentication processor is added to the SpringSecurity

@Configuration
@EnableWebSecurity
public class WebMvcSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAuthenticationFailureHandler failureHandler;

    @Autowired
    private MyAuthenticationSuccessHandler successHandler;


    @Override
    protected void configure(HttpSecurity http) throws Exception {

         http.formLogin()
         .successHandler(successHandler)
         .failureHandler(failureHandler)
         .and().authorizeRequests().anyRequest().authenticated();

    }

}

Such certification process will be able to come to our own definition of certified processors.

Above, if wrong, please point out thank you.

Guess you like

Origin blog.csdn.net/zyxwvuuvwxyz/article/details/102747149