解决在CAS中的跨域请求问题

1.场景描述

现有微服务a和微服务b,它们均通过一个CAS服务器C实现单点登录。在微服务a的web页面需要触发一段js脚本,这段脚本会通过http的get请求来调用微服务b的相关服务,实现对数据库的相关操作。

2.问题描述与分析

微服务a对微服务b的跨域请求问题

由于微服务a和微服务b处于不同的域(IP或端口不完全相同),又由于微服务a调用微服务b是通过js脚本,所以浏览器会对这样的跨域请求做限制。发起跨域请求的浏览器会在请求报文头里的Origin字段里指明源域(即它本身)的地址。响应的一方需要在应答报文头的Access-Control-Allow-Origin字段里指明被允许访问的域的地址,最后发起跨域请求的浏览器会先检验这个字段,再决定是否解析及处理该响应报文。所以该场景就需要我们在响应一方的报文头里加入Control-Allow-Origin字段及值。

微服务a与CAS服务器C之间的跨域请求问题

当微服务a能够正常解析并处理微服务b的响应报文的时候,会发现这是一个状态码为302的重定向报文。因为微服务b在解析到微服务a的请求报文的url的时候,会被微服务b中CAS的过滤器匹配到,做身份验证的操作,即重定向到CAS服务器做认证。此时,微服务a会发起第二次跨域请求,响应的域是CAS服务器C处在的域。所以这时,我们同样需要在服务器C上做类似上述在微服务b上的操作。

身份验证时,对cookie的操作问题

由于CAS做验证,需要获取其cookie。所以微服务a发起的跨域请求,必须指明要带上cookie。

3.问题解决

微服务a发起跨域请求时,带上cookie,即{‘withCredentials’:true}。这里用的AngularJS

XMLHttpRequest.withCredentials 属性是一个Boolean类型,它指示了是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求。在同一个站点下使用withCredentials属性是无效的。

$http.get('http://localhost:9107/xxx,{'withCredentials':true}).success(
	function(response){
		 if(response.success){
			 alert("成功");
		 }else{
			 alert(response.message);
		 }		
	}	
);
微服务b响应跨域请求时,带上Access-Control-Allow-Origin
  • 微服务b下创建一个过滤器(这个过滤器要在安全框架的过滤器或者CAS的过滤器之前)
    web.xml

    <filter>  
    	<filter-name>CORSFilter</filter-name>  
    	<filter-class>com.xzt.filter.CORSFilter</filter-class>  
    	<init-param>
    		<param-name>encoding</param-name>
    		<param-value>utf-8</param-value>
    	</init-param>
     </filter> 
    <filter-mapping> 
        <filter-name>CORSFilter</filter-name> 
        <url-pattern>/*</url-pattern> 
    </filter-mapping>
    
  • 新建java的过滤器类

    public class CORSFilter implements Filter{
    
    	@Override
    	public void init(FilterConfig filterConfig) throws ServletException {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    			throws IOException, ServletException {
    		System.out.println("进入过滤器CORSFilter");
    		HttpServletResponse resp = (HttpServletResponse)response;
    		HttpServletRequest req = (HttpServletRequest)request;
    		String origin = req.getHeader("Origin");
    		//这种方式可以灵活的配置Access-Control-Allow-Origin
    		//Access-Control-Allow-Origin的值不要写*号,因为对于带有cookie的跨域请求,浏览器不支持这种宽松的策略
    		resp.setHeader("Access-Control-Allow-Origin", origin);//可以访问的域
    		resp.setHeader("Access-Control-Allow-Credentials", "true");//如果操作cookie,必须加上这句话
    		chain.doFilter(request, response);
    	}
    
    	@Override
    	public void destroy() {
    		// TODO Auto-generated method stub
    		
    	}
    
    }
    
在CAS服务器C上,配置跨域请求
  • 在cas的工程路径下修改web.xml,添加过滤器
    cas/WEB-INF/web.xml

    <filter>
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
        <init-param>
         <param-name>cors.allowOrigin</param-name>
            <param-value>*</param-value>
        </init-param>
        <init-param>
         <param-name>cors.supportedMethods</param-name>
            <param-value>GET, POST, HEAD, PUT, DELETE</param-value>
        </init-param>
        <init-param>
         <param-name>cors.supportedHeaders</param-name>
            <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value>
        </init-param>
        <init-param>
            <param-name>cors.exposedHeaders</param-name>
            <param-value>Set-Cookie</param-value>
        </init-param>
        <init-param>
            <param-name>cors.supportsCredentials</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
  • 添加依赖
    cors-filter-1.7.0.wso2v1.jar java-property-utils-1.9.jar 这两个包放到
    cas/WEB-INF/lib路径下

    注:cors-filter-1.7.0.wso2v1.jar的原始下载路径找不到了。这里是我上传的 cas实现单点登录的相关依赖

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值