Cas客户端源码分析

同花顺

cas-client中有两个过滤器,客户端的过滤器用处在于与cas-server进行交互。

AuthenticationFilter

1、从session中获取名为CONST_CAS_ASSERTION/_const_cas_assertion_的session,判断存在与否。
存在就放行,执行下一个过滤器,不存在则重定向到认证界面。

2、判断ticket是否存在。
存在就放行,执行下一个过滤器,不存在则重定向到认证界面。

TicketValidationFilter

1、判断ticket是否存在。
存在就验证,不存在则执行下一个过滤器。

2、如果验证成功,session会以"const_cas_assertion"的名称保存assertion对象,
创建名为CONST_CAS_ASSERTION/_const_cas_assertion_的session。
继续处理下一个过滤器。

注意:cas-server认证通过后在server端留下了TGT,客户端同样的也有它自己子系统的session。

AuthenticationFilter

1、浏览器访问客户端A。

2、经过客户端A的Cas认证过滤器,在过滤器内部执行操作:

  • 首先判断存在子系统session吗。
  • 不存在,继续往下走。
  • 判断请求中是否存在ST。
  • 不存在,重定向至Cas认证界面。

3、现在已经认证成功了,再次访问客户端,同样进入Cas认证过滤器,在过滤器内部执行操作:

  • 首先判断存在子系统session吗。
  • 不存在,继续往下走。
  • 判断请求中是否存在ST。
  • 存在,放行,进入校验过滤器。

Tips:

有人很疑惑,为什么在客户端经过两次判断呢,仅仅判断session不就可以了吗?

通过源码可以发现,在第三步操作中,此时子系统中是没有session的,只有经过校验过滤器后,子系统中才有了session。


package org.jasig.cas.client.authentication;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.validation.Assertion;

public class AuthenticationFilter extends AbstractCasFilter {
    private String casServerLoginUrl;
    private boolean renew = false;
    private boolean gateway = false;
    private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl();

    public final void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        HttpSession session = request.getSession(false);
        //判断子系统中是否存在session
        Assertion assertion = session != null ? (Assertion)session.getAttribute("_const_cas_assertion_") : null;
        if (assertion != null) {
            filterChain.doFilter(request, response);
        } else {
        	//目标地址
            String serviceUrl = this.constructServiceUrl(request, response);
       		//判断请求中是否存在ST
            String ticket = CommonUtils.safeGetParameter(request, this.getArtifactParameterName());
            boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
       	 	//如果ST存在,则放行;不存在,则重定向至Cas认证界面
            if (!CommonUtils.isNotBlank(ticket) && !wasGatewayed) {
                this.log.debug("no ticket and no assertion found");
                String modifiedServiceUrl;
                if (this.gateway) {
                    this.log.debug("setting gateway attribute in session");
                    modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
                } else {
                    modifiedServiceUrl = serviceUrl;
                }

                if (this.log.isDebugEnabled()) {
                    this.log.debug("Constructed service url: " + modifiedServiceUrl);
                }
				//Cas认证界面
                String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, this.getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
                if (this.log.isDebugEnabled()) {
                    this.log.debug("redirecting to \"" + urlToRedirectTo + "\"");
                }

                response.sendRedirect(urlToRedirectTo);
            } else {
            //存在ST,放行。
                filterChain.doFilter(request, response);
            }
        }
    }
}

TicketValidationFilter

1、访问客户端的请求,经过了第一个过滤器,说明已经是认证过的,但是要判断一下ST是否是亲生的,即校验ST。

2、校验通过,存入Session,重定向至目标服务地址。


package org.jasig.cas.client.validation;

import java.io.IOException;
import javax.net.ssl.HostnameVerifier;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.ReflectUtils;

public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
    private TicketValidator ticketValidator;
    private boolean redirectAfterValidation = false;
    private boolean exceptionOnValidationFailure = true;
    private boolean useSession = true;

   

    public final void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        if (this.preFilter(servletRequest, servletResponse, filterChain)) {
			//将servletRequest,servletResponse强转为HttpServletRequest ,HttpServletResponse 。
			//过滤器中为ServletRequest,ServletResponse,但是拦截器以及我们的Controller中使用的都是HttpServletRequest,HttpServletResponse。
			//增加了针对于Http协议的方法。
            HttpServletRequest request = (HttpServletRequest)servletRequest;
            HttpServletResponse response = (HttpServletResponse)servletResponse;
            //获取ST
            String ticket = CommonUtils.safeGetParameter(request, this.getArtifactParameterName());
            //判断ST是否为空,不为空进行校验。
            if (CommonUtils.isNotBlank(ticket)) {
                if (this.log.isDebugEnabled()) {
                    this.log.debug("Attempting to validate ticket: " + ticket);
                }

                try {
                    Assertion assertion = this.ticketValidator.validate(ticket, this.constructServiceUrl(request, response));
                    if (this.log.isDebugEnabled()) {
                        this.log.debug("Successfully authenticated user: " + assertion.getPrincipal().getName());
                    }
					//校验通过,request设置assertion 
                    request.setAttribute("_const_cas_assertion_", assertion);
                    
                    if (this.useSession) {
                    //根据过滤器参数设置,判断true/false  
                    request.getSession().setAttribute("_const_cas_assertion_", assertion);
                    }

                    this.onSuccessfulValidation(request, response, assertion);
                    if (this.redirectAfterValidation) {
                        this.log.debug("Redirecting after successful ticket validation.");
					//重定向至目标服务地址
                     response.sendRedirect(this.constructServiceUrl(request, response));
                        return;
                    }
                } catch (TicketValidationException var8) {
                    response.setStatus(403);
                    this.log.warn(var8, var8);
                    this.onFailedValidation(request, response);
                    if (this.exceptionOnValidationFailure) {
                        throw new ServletException(var8);
                    }

                    return;
                }
            }

            filterChain.doFilter(request, response);
        }
    }

  
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值