目录
一、产生跨域的原因
二、错误描述
三、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>