由于OPTIONS
预检请求时没有携带token或cookie,shiro认为是未登录状态,则直接重定向到登录路径,前端控制台抛出Redirect is not allowed for a preflight request
预检请求不允许重定向,导致我一直认为时跨域问题,参考大佬博客之后得知需要重写shiro的登录认证过滤器,放行所有的OPTIONS
请求,现已解决该问题,在此记录一下,
import com.java.fang.common.utils.R;
import org.apache.shiro.web.filter.authc.UserFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class ShiroUserFilter extends UserFilter {
/**
* 在访问过来的时候检测是否为OPTIONS请求,如果是就直接返回true
*/
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpServletRequest httpRequest = (HttpServletRequest) request;
if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
setHeader(httpRequest,httpResponse);
return true;
}
return super.preHandle(request,response);
}
/**
* 该方法会在验证失败后调用,这里由于是前后端分离,后台不控制页面跳转
* 因此重写改成传输JSON数据
*/
@Override
protected void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException, IOException {
saveRequest(request);
setHeader((HttpServletRequest) request,(HttpServletResponse) response);
PrintWriter out = response.getWriter();
//自己控制返回的json数据
out.println(R.error(10000,"认证失败"));
out.flush();
out.close();
}
/**
* 为response设置header,实现跨域
*/
private void setHeader(HttpServletRequest request, HttpServletResponse response){
//跨域的header设置
response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", request.getMethod());
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
//防止乱码,适用于传输JSON数据
response.setHeader("Content-Type","application/json;charset=UTF-8");
response.setStatus(HttpStatus.OK.value());
}
}
重写过滤器后需要把自定义的过滤器添加到shiro中
// 在shiro配置文件中添加一下代码
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(){
ShiroFilterFactoryBean factoryFilter = new ShiroFilterFactoryBean();
Map<String, Filter> map = factoryFilter.getFilters();
map.put("authc",new ShiroUserFilter());
factoryFilter.setFilters(map);
//以下是其他配置
........
}