解决在CAS中的跨域请求问题
场景描述现有微服务a和微服务b,它们均通过一个CAS服务器C实现单点登录。在微服务a的web页面需要触发一段js脚本,这段脚本会通过http的get请求来调用微服务b的相关服务,实现对数据库的相关操作。问题描述与分析微服务a对微服务b的跨域请求问题由于微服务a和微服务b处于不同的域(IP或端口不完全相同),又由于微服务a调用微服务b是通过js脚本,所以浏览器会对这样的跨域请求做限制。发起跨域请求的
文章目录
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实现单点登录的相关依赖
更多推荐
所有评论(0)