CAS应用端异常解决

说明:因为当在浏览器的URL行输入要访问应用的URL后跟无效的ticket时,原有的CAS应用端过滤器会抛出异常,所以加入以下红色部分的代码。

 

package edu.yale.its.tp.cas.client.filter;

import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

import edu.yale.its.tp.cas.client.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

 


public class CASFilter implements Filter {

    private static Log log = LogFactory.getLog(CASFilter.class);

    // Filter initialization parameters
    
   public final static String LOGIN_INIT_PARAM = "edu.yale.its.tp.cas.client.filter.loginUrl";    
   

   public final static String VALIDATE_INIT_PARAM = "edu.yale.its.tp.cas.client.filter.validateUrl";    
  

   public final static String SERVICE_INIT_PARAM = "edu.yale.its.tp.cas.client.filter.serviceUrl";    
   

   public final static String SERVERNAME_INIT_PARAM = "edu.yale.its.tp.cas.client.filter.serverName";
    
   public final static String RENEW_INIT_PARAM = "edu.yale.its.tp.cas.client.filter.renew";    
  

   public final static String AUTHORIZED_PROXY_INIT_PARAM = "edu.yale.its.tp.cas.client.filter.authorizedProxy";
    
   public final static String PROXY_CALLBACK_INIT_PARAM = "edu.yale.its.tp.cas.client.filter.proxyCallbackUrl";    
   

   public final static String WRAP_REQUESTS_INIT_PARAM = "edu.yale.its.tp.cas.client.filter.wrapRequest";

    
   public final static String GATEWAY_INIT_PARAM = "edu.yale.its.tp.cas.client.filter.gateway";
   
    // Session attributes used by this filter

    /** <p>Session attribute in which the username is stored.</p> */
    public final static String CAS_FILTER_USER =
        "edu.yale.its.tp.cas.client.filter.user";
   
    /**
     * Session attribute in which the CASReceipt is stored.
     */
    public final static String CAS_FILTER_RECEIPT =
        "edu.yale.its.tp.cas.client.filter.receipt";
   
    /**
     * Session attribute in which internally used gateway
     * attribute is stored.
     */
    private static final String CAS_FILTER_GATEWAYED =
        "edu.yale.its.tp.cas.client.filter.didGateway";
       

    //*********************************************************************
    // Configuration state

    /** Secure URL whereat CAS offers its login service. */
    private String casLogin;
    /** Secure URL whereat CAS offers its CAS 2.0 validate service */
    private String casValidate;
    /** Filtered service URL for use as service parameter to login and validate */
    private String casServiceUrl;
    /** Name of server, for use in assembling service URL for use as service parameter to login and validate. */
    private String casServerName;
    /** Secure URL whereto this filter should ask CAS to send Proxy Granting Tickets. */
    private String casProxyCallbackUrl;
   
    /** True if renew parameter should be set on login and validate */
    private boolean casRenew;
   
    /** True if this filter should wrap requests to expose authenticated user as getRemoteUser(); */
    private boolean wrapRequest;
   
    /** True if this filter should set gateway=true on login redirect */
    private boolean casGateway = false;
   
    /**
     * List of ProxyTicketReceptor URLs of services authorized to proxy to the path
     * behind this filter.
     */
    private List authorizedProxies = new ArrayList();

    //*********************************************************************
    // Initialization

    public void init(FilterConfig config) throws ServletException {
        casLogin =
            config.getInitParameter(
                LOGIN_INIT_PARAM);
        casValidate =
            config.getInitParameter(
                VALIDATE_INIT_PARAM);
        casServiceUrl =
            config.getInitParameter(
                SERVICE_INIT_PARAM);
        String casAuthorizedProxy =
            config.getInitParameter(
                AUTHORIZED_PROXY_INIT_PARAM);
        casRenew =
            Boolean.valueOf(config.getInitParameter(RENEW_INIT_PARAM)).booleanValue();
        casServerName =
            config.getInitParameter(
                SERVERNAME_INIT_PARAM);
        casProxyCallbackUrl =
            config.getInitParameter(
                PROXY_CALLBACK_INIT_PARAM);
        wrapRequest =
            Boolean
                .valueOf(
                    config.getInitParameter(
                        WRAP_REQUESTS_INIT_PARAM))
                .booleanValue();
        casGateway =
            Boolean
                .valueOf(
                    config.getInitParameter(
                        GATEWAY_INIT_PARAM))
                .booleanValue();

        if (casGateway && Boolean.valueOf(casRenew).booleanValue()) {
            throw new ServletException("gateway and renew cannot both be true in filter configuration");
        }
        if (casServerName != null && casServiceUrl != null) {
            throw new ServletException("serverName and serviceUrl cannot both be set: choose one.");
        }
        if (casServerName == null && casServiceUrl == null) {
            throw new ServletException("one of serverName or serviceUrl must be set.");
        }
        if (casServiceUrl != null){
            if (! (casServiceUrl.startsWith("https://")|| (casServiceUrl.startsWith("http://") ))){
                throw new ServletException("service URL must start with http:// or https://; its current value is [" + casServiceUrl + "]");
            }
        }
       
        if (casValidate == null){
            throw new ServletException("validateUrl parameter must be set.");
        }
        if (! casValidate.startsWith("https://")){
            throw new ServletException("validateUrl must start with https://, its current value is [" + casValidate + "]");
        }
       
        if (casAuthorizedProxy != null){
           
            // parse and remember authorized proxies
            StringTokenizer casProxies =
                new StringTokenizer(casAuthorizedProxy);
            while (casProxies.hasMoreTokens()) {
                String anAuthorizedProxy = casProxies.nextToken();
                if (!anAuthorizedProxy.startsWith("https://")){
                    throw new ServletException("CASFilter initialization parameter for authorized proxies " +
                            "must be a whitespace delimited list of authorized proxies.  " +
                            "Authorized proxies must be secure (https) addresses.  This one wasn't: [" + anAuthorizedProxy + "]");
                }
                this.authorizedProxies.add(anAuthorizedProxy);
            }
        }
       
        if (log.isDebugEnabled()){
     log.debug(("CASFilter initialized as: [" + toString() + "]"));
        }
    }

    //*********************************************************************
    // Filter processing

    public void doFilter(
        ServletRequest request,
        ServletResponse response,
        FilterChain fc)
        throws ServletException, IOException {

    if (log.isTraceEnabled()){
     log.trace("entering doFilter()");
    }

        // make sure we've got an HTTP request
        if (!(request instanceof HttpServletRequest)
            || !(response instanceof HttpServletResponse)) {
             log.error("doFilter() called on a request or response that was not an HttpServletRequest or response.");
       throw new ServletException("CASFilter protects only HTTP resources");
            }
           

        // Is this a request for the proxy callback listener?  If so, pass
        // it through
        if (casProxyCallbackUrl != null
            && casProxyCallbackUrl.endsWith(
                ((HttpServletRequest) request).getRequestURI())
            && request.getParameter("pgtId") != null
            && request.getParameter("pgtIou") != null) {
             log.trace("passing through what we hope is CAS's request for proxy ticket receptor.");
            fc.doFilter(request, response);
            return;
        }

        // Wrap the request if desired
        if (wrapRequest) {
          log.trace("Wrapping request with CASFilterRequestWrapper.");
            request = new CASFilterRequestWrapper((HttpServletRequest) request);
        }

        HttpSession session = ((HttpServletRequest) request).getSession();

        // if our attribute's already present and valid, pass through the filter chain
        CASReceipt receipt = (CASReceipt) session.getAttribute(CAS_FILTER_RECEIPT);
        if (receipt != null && isReceiptAcceptable(receipt)) {
          log.trace("CAS_FILTER_RECEIPT attribute was present and acceptable - passing  request through filter..");
            fc.doFilter(request, response);
            return;
        }

        // otherwise, we need to authenticate via CAS
        String ticket = request.getParameter("ticket");

        // no ticket?  abort request processing and redirect
        if (ticket == null || ticket.equals("")) {
      log.trace("CAS ticket was not present on request.");
            // did we go through the gateway already?
            boolean didGateway =
                Boolean
                    .valueOf(
                        (String) session.getAttribute(
                            CAS_FILTER_GATEWAYED))
                    .booleanValue();

            if (casLogin == null) {
              //TODO: casLogin should probably be ensured to not be null at filter initialization. -awp9
              log.fatal("casLogin was not set, so filter cannot redirect request for authentication.");
                throw new ServletException(
                    "When CASFilter protects pages that do not receive a 'ticket' "
                        + "parameter, it needs a edu.yale.its.tp.cas.client.filter.loginUrl "
                        + "filter parameter");
            }
            if (!didGateway) {
              log.trace("Did not previously gateway.  Setting session attribute to true.");
                session.setAttribute(
                    CAS_FILTER_GATEWAYED,
                    "true");
                redirectToCAS(
                    (HttpServletRequest) request,
                    (HttpServletResponse) response);
                // abort chain
                return;
            } else {
              log.trace("Previously gatewayed.");
                // if we should be logged in, make sure validation succeeded
                if (casGateway
                    || session.getAttribute(CAS_FILTER_USER) != null) {
                     log.trace("casGateway was true and CAS_FILTER_USER set: passing request along filter chain.");
                    // continue processing the request
                    fc.doFilter(request, response);
                    return;
                } else {
                    // unknown state... redirect to CAS
                    session.setAttribute(
                        CAS_FILTER_GATEWAYED,
                        "true");
                    redirectToCAS(
                        (HttpServletRequest) request,
                        (HttpServletResponse) response);
                    // abort chain
                    return;
                }
            }
        }
       
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse rsp = (HttpServletResponse) response;
       
        try {
            receipt = getAuthenticatedUser((HttpServletRequest) request);
        } catch (CASAuthenticationException e) {
            log.error(e);           
            String casLoginURL=getCasLoginURL(req);
            //当ticket无效时,转向登录页面;否则,显示异常信息
            if (e.getMessage().indexOf("INVALID_TICKET") > 0) {             
                rsp.sendRedirect(casLoginURL);
            } else {             
                sendPageInfo(rsp);
            }
            return;
        }

        if (! isReceiptAcceptable(receipt)){
            throw new ServletException("Authentication was technically successful but rejected as a matter of policy. [" + receipt + "]");
        }
       
        // Store the authenticated user in the session
        if (session != null) { // probably unnecessary
            session.setAttribute(CAS_FILTER_USER, receipt.getUserName());
            session.setAttribute(CASFilter.CAS_FILTER_RECEIPT, receipt);
            // don't store extra unnecessary session state
            session.removeAttribute(
                CAS_FILTER_GATEWAYED);
        }
        if (log.isTraceEnabled()){
     log.trace("validated ticket to get authenticated receipt [" + receipt + "], now passing request along filter chain.");
        }
       
        // continue processing the request
        fc.doFilter(request, response);
        log.trace("returning from doFilter()");
    }

  

    private boolean isReceiptAcceptable(CASReceipt receipt) {
        if (receipt == null)
            throw new IllegalArgumentException("Cannot evaluate a null receipt.");         
        if (this.casRenew && !receipt.isPrimaryAuthentication()){
            return false;
        }
        if (receipt.isProxied()){
            if (! this.authorizedProxies.contains(receipt.getProxyingService())){
                return false;
            }
        }
        return true;
    }

 

    private CASReceipt getAuthenticatedUser(HttpServletRequest request)
        throws ServletException, CASAuthenticationException {
        log.trace("entering getAuthenticatedUser()");
        ProxyTicketValidator pv = null;
       
            pv = new ProxyTicketValidator();
            pv.setCasValidateUrl(casValidate);
            pv.setServiceTicket(request.getParameter("ticket"));
            pv.setService(getService(request));
            pv.setRenew(Boolean.valueOf(casRenew).booleanValue());
            if (casProxyCallbackUrl != null) {
                pv.setProxyCallbackUrl(casProxyCallbackUrl);
            }
            if (log.isDebugEnabled()) {
                log.debug(
                    "about to validate ProxyTicketValidator: [" + pv + "]");
            }
           
            return CASReceipt.getReceipt(pv);
       
    }

  

    private String getService(HttpServletRequest request)
        throws ServletException {

        log.trace("entering getService()");
        String serviceString;

        // ensure we have a server name or service name
        if (casServerName == null && casServiceUrl == null)
            throw new ServletException(
                "need one of the following configuration "
                    + "parameters: edu.yale.its.tp.cas.client.filter.serviceUrl or "
                    + "edu.yale.its.tp.cas.client.filter.serverName");

        // use the given string if it's provided
        if (casServiceUrl != null)
            serviceString = URLEncoder.encode(casServiceUrl);
        else
            // otherwise, return our best guess at the service
            serviceString = Util.getService(request, casServerName);
        if (log.isTraceEnabled()) {
            log.trace(
                "returning from getService() with service ["
                    + serviceString
                    + "]");
        }
        return serviceString;
    }

    /**
     * Redirects the user to CAS, determining the service from the request.
     */
    private void redirectToCAS(
        HttpServletRequest request,
        HttpServletResponse response)
        throws IOException, ServletException {
        if (log.isTraceEnabled()) {
            log.trace("entering redirectToCAS()");
        }

        String casLoginString =
            casLogin
                + "?service="
                + getService((HttpServletRequest) request)
                + ((casRenew)
                    ? "&renew=true"
                    : "")
                + (casGateway ? "&gateway=true" : "");

        if (log.isDebugEnabled()) {
            log.debug("Redirecting browser to [" + casLoginString + ")");
        }
        ((HttpServletResponse) response).sendRedirect(casLoginString);

        if (log.isTraceEnabled()) {
            log.trace("returning from redirectToCAS()");
        }
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("[CASFilter:");
        sb.append(" casGateway=");
        sb.append(this.casGateway);
        sb.append(" wrapRequest=");
        sb.append(this.wrapRequest);
       
        sb.append(" casAuthorizedProxies=[");
        sb.append(this.authorizedProxies);
        sb.append("]");
       
        if (this.casLogin != null) {
            sb.append(" casLogin=[");
            sb.append(this.casLogin);
            sb.append("]");
        } else {
            sb.append(" casLogin=NULL!!!!!");
        }
       
        if (this.casProxyCallbackUrl != null) {
            sb.append(" casProxyCallbackUrl=[");
            sb.append(casProxyCallbackUrl);
            sb.append("]");
        }
       
        if (this.casRenew) {
            sb.append(" casRenew=true");
        }
       
        if (this.casServerName != null) {
            sb.append(" casServerName=[");
            sb.append(casServerName);
            sb.append("]");
        }
       
        if (this.casServiceUrl != null) {
            sb.append(" casServiceUrl=[");
            sb.append(casServiceUrl);
            sb.append("]");
        }
       
        if (this.casValidate != null) {
            sb.append(" casValidate=[");
            sb.append(casValidate);
            sb.append("]");
        } else {
            sb.append(" casValidate=NULL!!!");
        }
       
        return sb.toString();
    }

    /* (non-Javadoc)
     * @see javax.servlet.Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
       
    }
   
    /***
     * 返回单点登录URL和访问的应用系统URL
     * @param request
     * @return String
     * @throws ServletException
     */
    private String getCasLoginURL(HttpServletRequest request) throws ServletException {
        StringBuilder sb = new StringBuilder();
        sb.append(casLogin).append("?service=").append(getService(request));
        return sb.toString();
    }
   
    /***
     * 显示异常信息
     * @param rsp
     * @param content
     * @throws IOException
     */   
    private void sendPageInfo(HttpServletResponse rsp) throws IOException {
        PrintWriter out = rsp.getWriter();
        try {        
         out.print("<body style='background-color: WhiteSmoke'>");
            out.print("<div style='font: 20;'>Not Found</div>");                      
            out.print("<hr/>");
            out.print("<div style='font: 20;'>Sorry,Error!</div>");
            out.print("</body>");           
        } finally {
            out.close();
        }
    }
   
}

你可能感兴趣的:(apache,浏览器,servlet,Go)