CAS 客户端登录验证

来源:互联网 发布:风险投资网络课程 编辑:程序博客网 时间:2024/06/06 09:57
  • 基于 cas-client v3.2.1
  • 参考文章:http://blog.csdn.net/dovejing/article/details/44426547

CAS 客户端登录验证的核心在于两个 Filter,如下

CAS 客户端的 web.xml

<!--该过滤器负责用户的认证工作--><filter>    <filter-name>CAS Authentication Filter</filter-name>    <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>    <init-param>        <param-name>casServerLoginUrl</param-name>        <param-value>http://pomer.com:8080/cas/login</param-value>    </init-param>    <init-param>        <param-name>serverName</param-name>        <param-value>http://pomer.com:8080/</param-value>    </init-param></filter><filter-mapping>    <filter-name>CAS Authentication Filter</filter-name>    <url-pattern>/*</url-pattern></filter-mapping><!-- 该过滤器配置负责对Ticket的校验工作--><filter>    <filter-name>CAS Validation Filter</filter-name>    <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>    <init-param>        <param-name>casServerUrlPrefix</param-name>        <param-value>http://pomer.com:8080/cas</param-value>    </init-param>    <init-param>        <param-name>serverName</param-name>        <param-value>http://pomer.com:8080/</param-value>    </init-param>    <init-param>        <param-name>renew</param-name>        <param-value>false</param-value>    </init-param>    <init-param>        <param-name>gateway</param-name>        <param-value>false</param-value>    </init-param>    <init-param>        <param-name>encoding</param-name>        <param-value>UTF-8</param-value>    </init-param></filter><filter-mapping>    <filter-name>CAS Validation Filter</filter-name>    <url-pattern>/*</url-pattern></filter-mapping>

进入第一个 Filter 源码,AuthenticationFilter 的 doFilter 方法

public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {    final HttpServletRequest request = (HttpServletRequest) servletRequest;    final HttpServletResponse response = (HttpServletResponse) servletResponse;    final HttpSession session = request.getSession(false);    <!--从 Session 中获取 Assertion,可以理解为是用户已登录的证明-->    final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;    if (assertion != null) {        <!--用户已登录,请求处理继续向前-->        filterChain.doFilter(request, response);        return;    }    <!--当前 url 处理成 service 参数(编码处理)-->    final String serviceUrl = constructServiceUrl(request, response);    <!--获取 ticket(即 ST)-->    final String ticket = CommonUtils.safeGetParameter(request,getArtifactParameterName());    final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);    if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {        <!--ticket 不为空,请求处理继续向前-->        filterChain.doFilter(request, response);        return;    }    final String modifiedServiceUrl;    <!--缺少 ST 和 Assertion,需要向 CAS 服务器申请认证-->    log.debug("no ticket and no assertion found");    if (this.gateway) {        log.debug("setting gateway attribute in session");        modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);    } else {        modifiedServiceUrl = serviceUrl;    }    if (log.isDebugEnabled()) {        log.debug("Constructed service url: " + modifiedServiceUrl);    }    <!--构造重定向 URL:http://pomer.com:8080/cas/login?service=xxx-->    final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);    if (log.isDebugEnabled()) {        log.debug("redirecting to \"" + urlToRedirectTo + "\"");    }    <!--开始重定向请求,接下来进入用户认证环节,移至 CAS 服务器处理-->    response.sendRedirect(urlToRedirectTo);}

进入第二个 Filter,Cas20ProxyReceivingTicketValidationFilter;doFilter 方法位于其父类 AbstractTicketValidationFilter,进入源码

public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {    if (!preFilter(servletRequest, servletResponse, filterChain)) {        return;    }    final HttpServletRequest request = (HttpServletRequest) servletRequest;    final HttpServletResponse response = (HttpServletResponse) servletResponse;    <!--获取 ticket(即 ST)-->    final String ticket = CommonUtils.safeGetParameter(request, getArtifactParameterName());    <!--如果 ticket 为空,说明是另一种情况:用户已登录-->    if (CommonUtils.isNotBlank(ticket)) {        <!--ticket 不为空,需要申请 CAS 服务器验证 ST-->        if (log.isDebugEnabled()) {            log.debug("Attempting to validate ticket: " + ticket);        }        try {            <!--发起 ST 认证,成功则返回 Assertion-->            final Assertion assertion = this.ticketValidator.validate(ticket, constructServiceUrl(request, response));            if (log.isDebugEnabled()) {                log.debug("Successfully authenticated user: " + assertion.getPrincipal().getName());            }            request.setAttribute(CONST_CAS_ASSERTION, assertion);            <!--往 Session 中存入 Assertion,作为用户已登录的证明-->            if (this.useSession) {                request.getSession().setAttribute(CONST_CAS_ASSERTION, assertion);            }            <!--在 ST 认证成功后执行,钩子方法-->            onSuccessfulValidation(request, response, assertion);            <!--重定向 URL:service-->            if (this.redirectAfterValidation) {                log. debug("Redirecting after successful ticket validation.");                response.sendRedirect(constructServiceUrl(request, response));                return;            }        } catch (final TicketValidationException e) {            response.setStatus(HttpServletResponse.SC_FORBIDDEN);            log.warn(e, e);            <!--在 ST 认证失败后执行,钩子方法-->            onFailedValidation(request, response);            if (this.exceptionOnValidationFailure) {                throw new ServletException(e);            }            return;        }    }    <!--到达这里表示用户已登录,请求处理继续向前-->    filterChain.doFilter(request, response);}
  • CAS 交互流程:http://blog.csdn.net/pomer_huang/article/details/76862386
  • CAS 服务端登录验证流程(一):http://blog.csdn.net/pomer_huang/article/details/76862455
原创粉丝点击