首頁  >  文章  >  php教程  >  cros跨域配置

cros跨域配置

高洛峰
高洛峰原創
2016-12-14 13:14:301279瀏覽

前端應用為靜態站點且部署在http://web.xxx.com域下,後端應用發布REST API並部署在http://api.xxx.com域下,如何使前端應用程式透過AJAX跨域訪問後端應用呢?這需要使用到CORS技術來實現,這也是目前最好的解決方案了。

[CORS全稱為Cross Origin Resource Sharing(跨域資源共享),服務端只需新增相關回應頭訊息,即可實現客戶端發出AJAX跨域請求。 ]

CORS技術非常簡單,易於實現,目前絕大多數瀏覽器均已支援該技術(IE8瀏覽器也支援了),服務端可透過任何程式語言來實現,只要能將CORS響應頭寫入response對像中即可。

下面我們繼續擴展REST框架,透過CORS技術實現AJAX跨域存取。

首先,我們需要寫一個Filter,用於過濾所有的HTTP請求,並將CORS回應頭寫入response物件中,程式碼如下:

public class CorsFilter implements Filter {  
  
    private String allowOrigin;  
    private String allowMethods;  
    private String allowCredentials;  
    private String allowHeaders;  
    private String exposeHeaders;  
  
    @Override  
    public void init(FilterConfig filterConfig) throws ServletException {  
        allowOrigin = filterConfig.getInitParameter("allowOrigin");  
        allowMethods = filterConfig.getInitParameter("allowMethods");  
        allowCredentials = filterConfig.getInitParameter("allowCredentials");  
        allowHeaders = filterConfig.getInitParameter("allowHeaders");  
        exposeHeaders = filterConfig.getInitParameter("exposeHeaders");  
    }  
  
    @Override  
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {  
        HttpServletRequest request = (HttpServletRequest) req;  
        HttpServletResponse response = (HttpServletResponse) res;  
        if (StringUtil.isNotEmpty(allowOrigin)) {  
            List<String> allowOriginList = Arrays.asList(allowOrigin.split(","));  
            if (CollectionUtil.isNotEmpty(allowOriginList)) {  
                String currentOrigin = request.getHeader("Origin");  
                if (allowOriginList.contains(currentOrigin)) {  
                    response.setHeader("Access-Control-Allow-Origin", currentOrigin);  
                }  
            }  
        }  
        if (StringUtil.isNotEmpty(allowMethods)) {  
            response.setHeader("Access-Control-Allow-Methods", allowMethods);  
        }  
        if (StringUtil.isNotEmpty(allowCredentials)) {  
            response.setHeader("Access-Control-Allow-Credentials", allowCredentials);  
        }  
        if (StringUtil.isNotEmpty(allowHeaders)) {  
            response.setHeader("Access-Control-Allow-Headers", allowHeaders);  
        }  
        if (StringUtil.isNotEmpty(exposeHeaders)) {  
            response.setHeader("Access-Control-Expose-Headers", exposeHeaders);  
        }  
        chain.doFilter(req, res);  
    }  
  
    @Override  
    public void destroy() {  
    }  
}

以上CorsFilter將從web.xml中讀取相關Filter初始化參數,並將在處理HTTP請求時將這些參數寫入對應的CORS回應頭中,下面大致描述一下這些CORS回應頭的意義:


Access-Control-Allow-Origin:允許存取的客戶端域名,例如:http://web.xxx.com,若為*,則表示從任意網域都能訪問,即不做任何限制。

Access-Control-Allow-Methods:允許存取的方法名,多個方法名稱以逗號分割,例如:GET,POST,PUT,DELETE,OPTIONS。

Access-Control-Allow-Credentials:是否允許請求帶有驗證訊息,若要取得客戶端網域下的cookie時,需要將其設為true。

Access-Control-Allow-Headers:允許服務端存取的用戶端請求頭,多個請求頭用逗號分割,例如:Content-Type。

Access-Control-Expose-Headers:允許客戶端存取的服務端回應頭,多個回應頭用逗號分割。

需要注意的是,CORS規格中定義Access-Control-Allow-Origin只允許兩種取值,要麼為*,要麼為具體的域名,也就是說,不支援同時配置多個域名。為了解決跨多個域的問題,需要在程式碼中做一些處理,這裡將Filter初始化參數作為一個網域的集合(用逗號分隔),只需從目前請求中取得Origin請求頭,就知道從哪個網域中發出的請求,若該請求在以上允許的網域集合中,則將其放入Access-Control-Allow-Origin回應頭,這樣跨多個網域的問題就輕鬆解決了。

以下是web.xml中配置CorsFilter的方法:

<filter>  
    <filter-name>corsFilter</filter-name>  
    <filter-class>com.xxx.api.cors.CorsFilter</filter-class>  
    <init-param>  
        <param-name>allowOrigin</param-name>  
        <param-value>http://web.xxx.com</param-value>  
    </init-param>  
    <init-param>  
        <param-name>allowMethods</param-name>  
        <param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>  
    </init-param>  
    <init-param>  
        <param-name>allowCredentials</param-name>  
        <param-value>true</param-value>  
    </init-param>  
    <init-param>  
        <param-name>allowHeaders</param-name>  
        <param-value>Content-Type</param-value>  
    </init-param>  
</filter>  
<filter-mapping>  
    <filter-name>corsFilter</filter-name>  
    <url-pattern>/*</url-pattern>  
</filter-mapping>

完成以上過程即可實現AJAX跨域功能了,但似乎還有另一個問題,由於REST是無狀態的,後端應用發布的REST API可在使用者未登入的情況下被任意調用,這顯然是不安全的,如何解決這個問題?我們需要為REST請求提供安全機制。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn