CAS環境下的AJAX跨域

狀況說明:java

        在單點登陸的環境下,全部的文件上傳都是經過webuploader上傳到文件管理服務器。而webuploader的上傳能夠參考ajax的請求,至關因而跨域操做。web

        首先,跨域請求訪問的問題,能夠經過在文件服務器增長攔截器,修改請求頭來解決。ajax

package com.util;
 
import java.io.IOException;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
 
public class SimpleCORSFilter implements Filter {
 
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods",
                "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        chain.doFilter(req, res);
    }
 
    public void init(FilterConfig filterConfig) {
    }
 
    public void destroy() {
    }
 
}

 

        而在CAS的環境下,跨域的請求還會面臨登陸驗證的重定向,可是ajax是不支持重定向的,進而致使文件上傳的不成功。express

        查閱衆多資料,最後在看到org.jasig.cas.client.authentication.AuthenticationFilter才豁然開朗。apache

/**
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
 
package org.jasig.cas.client.authentication;
 
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.validation.Assertion;
 
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 java.io.IOException;
 
/**
 * Filter implementation to intercept all requests and attempt to authenticate
 * the user by redirecting them to CAS (unless the user has a ticket).
 * <p>
 * This filter allows you to specify the following parameters (at either the context-level or the filter-level):
 * <ul>
 * <li><code>casServerLoginUrl</code> - the url to log into CAS, i.e. https://cas.rutgers.edu/login</li>
 * <li><code>renew</code> - true/false on whether to use renew or not.</li>
 * <li><code>gateway</code> - true/false on whether to use gateway or not.</li>
 * </ul>
 *
 * <p>Please see AbstractCasFilter for additional properties.</p>
 *
 * @author Scott Battaglia
 * @version $Revision: 11768 $ $Date: 2007-02-07 15:44:16 -0500 (Wed, 07 Feb 2007) $
 * @since 3.0
 */
public class AuthenticationFilter extends AbstractCasFilter {
 
    /**
     * The URL to the CAS Server login.
     */
    private String casServerLoginUrl;
 
    /**
     * Whether to send the renew request or not.
     */
    private boolean renew = false;
 
    /**
     * Whether to send the gateway request or not.
     */
    private boolean gateway = false;
    
    private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl();
 
    protected void initInternal(final FilterConfig filterConfig) throws ServletException {
        if (!isIgnoreInitConfiguration()) {
            super.initInternal(filterConfig);
            setCasServerLoginUrl(getPropertyFromInitParams(filterConfig, "casServerLoginUrl", null));
            log.trace("Loaded CasServerLoginUrl parameter: " + this.casServerLoginUrl);
            setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
            log.trace("Loaded renew parameter: " + this.renew);
            setGateway(parseBoolean(getPropertyFromInitParams(filterConfig, "gateway", "false")));
            log.trace("Loaded gateway parameter: " + this.gateway);
 
            final String gatewayStorageClass = getPropertyFromInitParams(filterConfig, "gatewayStorageClass", null);
 
            if (gatewayStorageClass != null) {
                try {
                    this.gatewayStorage = (GatewayResolver) Class.forName(gatewayStorageClass).newInstance();
                } catch (final Exception e) {
                    log.error(e,e);
                    throw new ServletException(e);
                }
            }
        }
    }
 
    public void init() {
        super.init();
        CommonUtils.assertNotNull(this.casServerLoginUrl, "casServerLoginUrl cannot be null.");
    }
 
    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);
        final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;
 
        if (assertion != null) {
            filterChain.doFilter(request, response);
            return;
        }
 
        final String serviceUrl = constructServiceUrl(request, response);
        final String ticket = CommonUtils.safeGetParameter(request,getArtifactParameterName());
        final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
 
        if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {
            filterChain.doFilter(request, response);
            return;
        }
 
        final String modifiedServiceUrl;
 
        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);
        }
 
        final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
 
        if (log.isDebugEnabled()) {
            log.debug("redirecting to \"" + urlToRedirectTo + "\"");
        }
 
        response.sendRedirect(urlToRedirectTo);
    }
 
    public final void setRenew(final boolean renew) {
        this.renew = renew;
    }
 
    public final void setGateway(final boolean gateway) {
        this.gateway = gateway;
    }
 
    public final void setCasServerLoginUrl(final String casServerLoginUrl) {
        this.casServerLoginUrl = casServerLoginUrl;
    }
    
    public final void setGatewayStorage(final GatewayResolver gatewayStorage) {
    	this.gatewayStorage = gatewayStorage;
    }
}

 

        看到104行可知,每次的請求都會判斷session是否存在,若是session存在,則會繼續接下來的請求,不然重定向到CAS服務端。既然如此,則能夠在每次的ajax請求中帶上;jsessionid=********;這樣,就能夠每次的請求都能獲取到session。json

        那麼問題來了,如何在每次的請求提交前,在url上獲取文件上傳服務器的sessionid的cookie呢?在這裏我採用的是jsonp,在每次上傳組件初始化以前,採用jsonp發送初始化請求,獲取文件服務器上的sessionid,返回後綁定到請求的url地址後。經測試,問題解決。跨域

@Controller
public class InitController {
 
    @RequestMapping("init")
    @ResponseBody
    public String getId(HttpServletRequest req, HttpServletResponse res) {
        HttpSession session = req.getSession();
        res.setContentType("text/plain");
        String callbackFunName = req.getParameter("callbackparam");// 獲得js函數名稱
        String jsonp = "";
        if (session != null) {
            String id = session.getId();
            jsonp = "([ { jid:\"" + id + "\"}])";
        }
        return callbackFunName + jsonp;
    }
}

 

/* 初始化上傳信息 */
function initConfig() {
	$.ajax({  
		url:prefix+'/init',  
		data:'',  
		async:false,
		dataType: "jsonp",  
		jsonp: "callbackparam", //服務端用於接收callback調用的function名的參數   
		jsonpCallback: "success_jsonpCallback", //callback的function名稱,服務端會把名稱和data一塊兒傳遞回來 
		success:function(result) {
			uploaderInit();
		},  
		error:function(){
			alert("上傳信息初始化失敗!");
		},
		timeout:3000  
	}); 
}
function success_jsonpCallback(obj){
	if(obj.length>0&&obj[0].jid){
		var id = obj[0].jid;
		jid=';jsessionid='+id;
	}else{
		alert("上傳信息初始化失敗!");
	}
}

 

相關文章
相關標籤/搜索