1.首先我们需要配置一下跨域
import com.factory.utils.interceptor.AuthorizationInterceptor; import com.factory.utils.resolver.LoginUserHandlerMethodArgumentResolver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.*; import java.util.List; @Configuration public class WebConfig implements WebMvcConfigurer { //application.properties中添加允许跨域的地址 @Value("#{'${spring.config.allowedOrigins}'.split(',')}") private String[] allowedOrigins; @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins(allowedOrigins) .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") .allowCredentials(true).maxAge(3600); } }
当我们配置跨域之后依然会有跨域问题
2. OPTIONS 请求出现跨域
在跨域访问的场景下, 正式访问之前增加的一次预检性质访问,以确定能否正确获取所请求的资源.
通常是OPTIONS 请求正常返回status 200,然后才发起正式的GET/POST等访问,但因为Shiro配置了URL过滤, 对于OPTIONS Request也进行了拦截,所以无法继续访问.
解决方案 isAccessAllowed
让Shiro对OPTIONS Request不进行鉴权操作
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.core.annotation.Order;
import org.thymeleaf.util.StringUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* 解决因跨域问题第一次请求为OPTIONS 导致shiro以为没有登录而返回302
*
*/
@Order(1000)
public class MyFormAuthCorsFilter extends FormAuthenticationFilter {
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
// 获取当前登录
Subject subject = getSubject(request, response);
if (subject.getPrincipal() == null) {
// 使用response响应流返回数据到前台(因前端需要接受json数据,注意前后端跨域问题)
return false;
} else {
return true;
}
}
//isAccessAllowed
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
boolean allowed = super.isAccessAllowed(request, response, mappedValue);
if (!allowed) {
// 判断请求是否是options请求。
String method = WebUtils.toHttp(request).getMethod();
if (StringUtils.equalsIgnoreCase("OPTIONS", method)) {
return true;
}
}
return allowed;
}
}
Map<String, Filter> filters = new LinkedHashMap<>(); filters.put("authc", new MyFormAuthCorsFilter()); shiroFilter.setFilters(filters);