• Springboot security cas源码陶冶-ExceptionTranslationFilter


    拦截关键的两个异常,对异常进行处理。主要应用异常则跳转至cas服务端登录页面

    ExceptionTranslationFilter#doFilter-逻辑入口

    具体操作逻辑如下

    	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
    			throws IOException, ServletException {
    		HttpServletRequest request = (HttpServletRequest) req;
    		HttpServletResponse response = (HttpServletResponse) res;
    		//这里直接放行,看出来其主要处理的是异常发生的情况
    		try {
    			chain.doFilter(request, response);
    
    			logger.debug("Chain processed normally");
    		}
    		//IO异常直接抛出
    		catch (IOException ex) {
    			throw ex;
    		}
    		catch (Exception ex) {
    			//提取发生的异常
    			Throwable[] causeChain = throwableAnalyzer.determineCauseChain(ex);
    			//首先获取是否含有AuthenticationException异常
    			RuntimeException ase = (AuthenticationException) throwableAnalyzer
    					.getFirstThrowableOfType(AuthenticationException.class, causeChain);
    
    			if (ase == null) {
    				//没有AuthenticationException异常则尝试获取AccessDeniedException异常
    				ase = (AccessDeniedException) throwableAnalyzer.getFirstThrowableOfType(
    						AccessDeniedException.class, causeChain);
    			}
    
    			if (ase != null) {
    				//处理指定的这两个关键异常
    				handleSpringSecurityException(request, response, chain, ase);
    			}
    			else {
    				//如果关键异常都没有则直接抛出
    				if (ex instanceof ServletException) {
    					throw (ServletException) ex;
    				}
    				else if (ex instanceof RuntimeException) {
    					throw (RuntimeException) ex;
    				}
    				throw new RuntimeException(ex);
    			}
    		}
    	}
    

    由以上代码我们只需要着重分析下handleSpringSecurityException()方法即可

    ExceptionTranslationFilter#handleSpringSecurityException-处理spring安全异常

    源码如下

    	private void handleSpringSecurityException(HttpServletRequest request,
    			HttpServletResponse response, FilterChain chain, RuntimeException exception)
    			throws IOException, ServletException {
    		if (exception instanceof AuthenticationException) {
    			//转发请求至cas服务端登录页面
    			sendStartAuthentication(request, response, chain,
    					(AuthenticationException) exception);
    		}
    		else if (exception instanceof AccessDeniedException) {
    		//首先判断是否Authentication凭证是否为AnonymousAuthenticationToken
    			if (authenticationTrustResolver.isAnonymous(SecurityContextHolder
    					.getContext().getAuthentication())) {
    				//对AnonymousAuthenticationToken类型的请求转发cas服务端登录请求页面
    				sendStartAuthentication(
    						request,
    						response,
    						chain,
    						new InsufficientAuthenticationException(
    								"Full authentication is required to access this resource"));
    			}
    			else {
    				//对于非AnonymousAuthenticationToken类型的请求,比如UsernamePasswordAuthenticationToken/CasAuthenticationToken则直接将异常信息写出到页面
    				accessDeniedHandler.handle(request, response,
    						(AccessDeniedException) exception);
    			}
    		}
    	}
    

    紧接着我们看ExceptionTranslationFilter#sendStartAuthentication()方法

    	protected void sendStartAuthentication(HttpServletRequest request,
    			HttpServletResponse response, FilterChain chain,
    			AuthenticationException reason) throws ServletException, IOException {
    		//转发前先清楚凭证信息
    		SecurityContextHolder.getContext().setAuthentication(null);
    		requestCache.saveRequest(request, response);
    		
    		//通过AuthenticationEntryPoint对象转发请求,常见为CasAuthenticationEntryPoint
    		authenticationEntryPoint.commence(request, response, reason);
    	}
    

    CasAuthenticationEntryPoint#commence-cas服务端登录请求转发

    直接查看源码,代码很简单

    	public final void commence(final HttpServletRequest servletRequest,
    			final HttpServletResponse response,
    			final AuthenticationException authenticationException) throws IOException,
    			ServletException {
    		//创建service回调参数路径
    		final String urlEncodedService = createServiceUrl(servletRequest, response);
    		//cas服务端登录请求路径拼装,即后面会添加service参数
    		final String redirectUrl = createRedirectUrl(urlEncodedService);
    
    		//模板方法,供子类复写
    		preCommence(servletRequest, response);
    		//直接转发
    		response.sendRedirect(redirectUrl);
    	}
    

    CasAuthenticationEntryPoint以下属性必须配置

    1. loginUrl-cas服务端的登录地址,比如https://www.examplecasserver.com/cas/login
    2. ServiceProperties-回调路径的配置,主要是service属性,此处一般为应用的主页地址

    小结

    1. ExceptionTranslationFilter的执行逻辑比较简单,主要是接受AccessDeniedExceptionAuthenticationException两大请求,并最终转发至cas服务端登录界面

    2. ExceptionTranslationFilter的搭档是FilterSecurityInterceptor,其介绍可查看>>>Springboot security cas源码陶冶-FilterSecurityInterceptor

    3. Note:CasAuthenticationEntryPoint在配置service回调地址时,不可为应用的登录请求地址,不然会提前被CasAuthenticationFilter拦截直接输出错误至页面了

  • 相关阅读:
    线性回归和 逻辑回归 的思考(参考斯坦福 吴恩达的课程)
    数据结构算法基础-内部排序算法
    机器学习《test》
    day1.接口测试(概念、Postman、SoapUI、jmeter)
    SQL2000 3核6核 CUP 安装SP4
    SQL常用语句
    SQL SERVER 2000数据库置疑处理
    常用终端命令
    c++ 位操作
    计算机为什么用补码存储数据?
  • 原文地址:https://www.cnblogs.com/question-sky/p/7066117.html
Copyright © 2020-2023  润新知