CAS环境下的AJAX跨域
情况说明: 在单点登录的环境下,所有的文件上传都是通过webuploader上传到文件管理服务器。而webuploader的上传可以参考ajax的请求,相当于是跨域操作。 首先,跨域请求访问的问题,可以通过在文件服务器增加拦截器,修改请求头来解决。 packagecom.util; importjava.io.IOException; importjavax.servlet.Filter; importjavax.servlet.FilterChain; importjavax.servlet.FilterConfig; importjavax.servlet.ServletException; importjavax.servlet.ServletRequest; importjavax.servlet.ServletResponse; importjavax.servlet.http.HttpServletResponse; publicclassSimpleCORSFilterimplementsFilter{ publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain)throwsIOException,ServletException{ HttpServletResponseresponse=(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); } publicvoidinit(FilterConfigfilterConfig){ } publicvoiddestroy(){ } } 而在CAS的环境下,跨域的请求还会面临登录验证的重定向,但是ajax是不支持重定向的,进而导致文件上传的不成功。
查阅众多资料,最后在看到org.jasig.cas.client.authentication.AuthenticationFilter才豁然开朗。 /** *LicensedtoJasigunderoneormorecontributorlicense *agreements.SeetheNOTICEfiledistributedwiththiswork *foradditionalinformationregardingcopyrightownership. *JasiglicensesthisfiletoyouundertheApacheLicense,*Version2.0(the"License");youmaynotusethisfile *exceptincompliancewiththeLicense.Youmayobtaina *copyoftheLicenseat: * *http://www.apache.org/licenses/LICENSE-2.0 * *Unlessrequiredbyapplicablelaworagreedtoinwriting,*softwaredistributedundertheLicenseisdistributedon *an"ASIS"BASIS,WITHOUTWARRANTIESORCONDITIONSOFANY *KIND,eitherexpressorimplied.SeetheLicenseforthe *specificlanguagegoverningpermissionsandlimitations *undertheLicense. */ packageorg.jasig.cas.client.authentication; importorg.jasig.cas.client.util.AbstractCasFilter; importorg.jasig.cas.client.util.CommonUtils; importorg.jasig.cas.client.validation.Assertion; importjavax.servlet.FilterChain; importjavax.servlet.FilterConfig; importjavax.servlet.ServletException; importjavax.servlet.ServletRequest; importjavax.servlet.ServletResponse; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importjavax.servlet.http.HttpSession; importjava.io.IOException; /** *Filterimplementationtointerceptallrequestsandattempttoauthenticate *theuserbyredirectingthemtoCAS(unlesstheuserhasaticket). *<p> *Thisfilterallowsyoutospecifythefollowingparameters(ateitherthecontext-levelorthefilter-level): *<ul> *<li><code>casServerLoginUrl</code>-theurltologintoCAS,i.e.https://cas.rutgers.edu/login</li> *<li><code>renew</code>-true/falSEOnwhethertouserenewornot.</li> *<li><code>gateway</code>-true/falSEOnwhethertousegatewayornot.</li> *</ul> * *<p>PleaseseeAbstractCasFilterforadditionalproperties.</p> * *@authorScottBattaglia *@version$Revision:11768$$Date:2007-02-0715:44:16-0500(Wed,07Feb2007)$ *@since3.0 */ publicclassAuthenticationFilterextendsAbstractCasFilter{ /** *TheURLtotheCASServerlogin. */ privateStringcasServerLoginUrl; /** *Whethertosendtherenewrequestornot. */ privatebooleanrenew=false; /** *Whethertosendthegatewayrequestornot. */ privatebooleangateway=false; privateGatewayResolvergatewayStorage=newDefaultGatewayResolverImpl(); protectedvoidinitInternal(finalFilterConfigfilterConfig)throwsServletException{ if(!isIgnoreInitConfiguration()){ super.initInternal(filterConfig); setCasServerLoginUrl(getPropertyFromInitParams(filterConfig,"casServerLoginUrl",null)); log.trace("LoadedCasServerLoginUrlparameter:"+this.casServerLoginUrl); setRenew(parseBoolean(getPropertyFromInitParams(filterConfig,"renew","false"))); log.trace("Loadedrenewparameter:"+this.renew); setGateway(parseBoolean(getPropertyFromInitParams(filterConfig,"gateway","false"))); log.trace("Loadedgatewayparameter:"+this.gateway); finalStringgatewayStorageClass=getPropertyFromInitParams(filterConfig,"gatewayStorageClass",null); if(gatewayStorageClass!=null){ try{ this.gatewayStorage=(GatewayResolver)Class.forName(gatewayStorageClass).newInstance(); }catch(finalExceptione){ log.error(e,e); thrownewServletException(e); } } } } publicvoidinit(){ super.init(); CommonUtils.assertNotNull(this.casServerLoginUrl,"casServerLoginUrlcannotbenull."); } publicfinalvoiddoFilter(finalServletRequestservletRequest,finalServletResponseservletResponse,finalFilterChainfilterChain)throwsIOException,ServletException{ finalHttpServletRequestrequest=(HttpServletRequest)servletRequest; finalHttpServletResponseresponse=(HttpServletResponse)servletResponse; finalHttpSessionsession=request.getSession(false); finalAssertionassertion=session!=null?(Assertion)session.getAttribute(CONST_CAS_ASSERTION):null; if(assertion!=null){ filterChain.doFilter(request,response); return; } finalStringserviceUrl=constructServiceUrl(request,response); finalStringticket=CommonUtils.safeGetParameter(request,getArtifactParameterName()); finalbooleanwasGatewayed=this.gatewayStorage.hasGatewayedAlready(request,serviceUrl); if(CommonUtils.isNotBlank(ticket)||wasGatewayed){ filterChain.doFilter(request,response); return; } finalStringmodifiedServiceUrl; log.debug("noticketandnoassertionfound"); if(this.gateway){ log.debug("settinggatewayattributeinsession"); modifiedServiceUrl=this.gatewayStorage.storeGatewayInformation(request,serviceUrl); }else{ modifiedServiceUrl=serviceUrl; } if(log.isDebugEnabled()){ log.debug("Constructedserviceurl:"+modifiedServiceUrl); } finalStringurlToRedirectTo=CommonUtils.constructRedirectUrl(this.casServerLoginUrl,getServiceParameterName(),modifiedServiceUrl,this.renew,this.gateway); if(log.isDebugEnabled()){ log.debug("redirectingto""+urlToRedirectTo+"""); } response.sendRedirect(urlToRedirectTo); } publicfinalvoidsetRenew(finalbooleanrenew){ this.renew=renew; } publicfinalvoidsetGateway(finalbooleangateway){ this.gateway=gateway; } publicfinalvoidsetCasServerLoginUrl(finalStringcasServerLoginUrl){ this.casServerLoginUrl=casServerLoginUrl; } publicfinalvoidsetGatewayStorage(finalGatewayResolvergatewayStorage){ this.gatewayStorage=gatewayStorage; } } 看到104行可知,每次的请求都会判断session是否存在,如果session存在,则会继续接下来的请求,否则重定向到CAS服务端。既然如此,则可以在每次的ajax请求中带上;jsessionid=********;这样,就可以每次的请求都能获取到session。 那么问题来了,如何在每次的请求提交前,在url上获取文件上传服务器的sessionid的cookie呢?在这里我采用的是jsonp,在每次上传组件初始化之前,采用jsonp发送初始化请求,获取文件服务器上的sessionid,返回后绑定到请求的url地址后。经测试,问题解决。 @Controller publicclassInitController{ @RequestMapping("init") @ResponseBody publicStringgetId(HttpServletRequestreq,HttpServletResponseres){ HttpSessionsession=req.getSession(); res.setContentType("text/plain"); StringcallbackFunName=req.getParameter("callbackparam");//得到js函数名称 Stringjsonp=""; if(session!=null){ Stringid=session.getId(); jsonp="([{jid:""+id+""}])"; } returncallbackFunName+jsonp; } } /*初始化上传信息*/ functioninitConfig(){ $.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 }); } functionsuccess_jsonpCallback(obj){ if(obj.length>0&&obj[0].jid){ varid=obj[0].jid; jid=';jsessionid='+id; }else{ alert("上传信息初始化失败!"); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |