目錄
一、產生跨域的原因
二、錯誤描述
三、HTTP訪問控制(CORS)
四、解決方案
1、@CrossOrigin 註解
2、設置頭部信息
3、配置攔截器
4、web.xml配置
5、HttpClient 轉發請求
6、spring-context.xml配置
五、帶token的跨域問題解決方案
4、web.xml配置
名詞解釋:
1、Content-Type:實體頭部用於指示資源的MIME類型 media type 。
2、Accept :用來告知(服務器)客戶端可以處理的內容類型,這種內容類型用MIME類型來表示。
3、Origin :表明預檢請求或實際請求的源站。
4、X-Requested-With:用來判斷一個請求是傳統的HTTP請求,還是Ajax請求。Ajax的請求一般都會帶上X-Requested-With頭域。
5、Last-Modified:標記請求的資源在服務器端最後被修改的時間。
配置代碼:
- 把 java-property-utils-1.9.1.jar 和 cors-filter-2.6.jar 這兩個jar包放到tomcat的lib目錄下,或者直接在pom.xml中添加依賴:
<!-- https://mvnrepository.com/artifact/com.thetransactioncompany/cors-filter -->
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.5</version>
</dependency>
- 打開tomcat的安裝目錄下的conf文件夾,找到web.xml文件,並將下列代碼添加進去(放在文件中間四百多行的位置即可),或者直接在項目中的web.xml進行添加。
<!-- 實現跨域 (filter配置放在其它所有filter的上面)-->
<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,OPTIONS</param-value>
</init-param>
<init-param>
<!-- 支持的頭部 -->
<param-name>cors.supportedHeaders</param-name>
<param-value>Access-Control-Allow-Origin,Content-Type,X-Requested-With,
Access-Control-Request-Method,Access-Control-Request-Headers,
Accept, Origin, Last-Modified</param-value>
</init-param>
<init-param>
<param-name>cors.exposedHeaders</param-name>
<param-value>Set-Cookie</param-value>
</init-param>
<init-param>
<!-- 允許瀏覽器讀取response的內容 -->
<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>
5、HttpClient 轉發請求
這種方式需要搭建一個與前端同源的後端,用於轉發請求
前端調用url:http://localhost:8080/library/findBookById?bookId=1
package test;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/findBookById")
public class FindBookByIdServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
String bookId = httpServletRequest.getParameter("bookId");
CloseableHttpClient httpClient = HttpClients.createDefault();
//創建get請求
HttpGet httpGet = new HttpGet("http://localhost:80/A/findBookById?userName="+bookId);
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
int code = httpResponse.getStatusLine().getStatusCode();
if(code == 200){
String result = EntityUtils.toString(httpResponse.getEntity());
httpServletResponse.getWriter().print(result);
}
httpResponse.close();
httpClient.close();
}
}
6、spring-context.xml配置
這裏使用到的值已經在上一篇文章已經解釋過了,這裏就不在贅述。
<!-- 接口跨域配置 -->
<mvc:cors>
<!-- * :所有請求 -->
<mvc:mapping path="/**" allowed-origins="*"
allowed-methods="POST, GET, OPTIONS, DELETE, PUT"
allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"
allow-credentials="true" />
</mvc:cors>
五、帶token的跨域問題解決方案
當請求攜帶token時,跨域的解決方案於上述方式差不多,只是需要多加一個表示token的字段。注意:這個字段不一定叫做token,要看後臺代碼是怎麼寫的
生成token的代碼:
解析token的代碼:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setCharacterEncoding("utf-8");
String token = request.getHeader("access_token");
}
注意上面和下面代碼的區別,生成token時,寫了“token”,但解析時解析的是“access_token”(這兩個命名可以隨意,但爲了可讀性,儘量寫一樣的)這時,請求攜帶的token命名爲“access_token”
則解決跨域問題時,只需在表示實際請求中允許攜帶的首部字段中加入“access_token”即可。
例如:
resp.setHeader("access_token","Access-Control-Allow-Headers",
"X-Requested-With, Content-Type, Authorization, Accept, Origin, User-Agent, Content-Range, Content-Disposition, Content-Description");
<init-param>
<!-- 支持的頭部 -->
<param-name>cors.supportedHeaders</param-name>
<param-value>access_token,
Access-Control-Allow-Origin,Content-Type,
X-Requested-With,Access-Control-Request-Method,
Access-Control-Request-Headers,Accept, Origin,
Last-Modified</param-value>
</init-param>