报错
Access to XMLHttpRequest at 'http://localhost:8081/teacherSelect' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
1、一开始对于登录界面
新增一个类实现 WebMvcConfigurer 接口,然后给这个类加上 @Configuration 注解,最后实现 addCorsMappings 方法就ok了。
@Configuration
public class CrosConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.maxAge(3600)
.allowCredentials(true);
}
}
2、但是进入主页面之后的请求还是报了之前的错误
原因
shiro 把 options 拦截了。
因为 options 没有挟带 cookie 。
现在让 shiro 不拦截 options
解决方法部分来源:
https://www.jianshu.com/p/5c637bfcc674
但是用了他的办法后还是不行,需要再加上一些代码
步骤
- 新建一个拦截器类 CorsInterceptor 实现 HandlerInterceptor 接口
package com.springboot.study.config;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class CorsInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "86400");
response.setHeader("Access-Control-Allow-Headers", "*");
// 如果是OPTIONS则结束请求
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
response.setStatus(HttpStatus.NO_CONTENT.value());
return false;
}
return true;
}
}
- 新增CrosConfig
package com.springboot.study.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
@Configuration
public class CrosConfig implements WebMvcConfigurer {
@Resource
private CorsInterceptor corsInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 跨域拦截器需放在最上面
registry.addInterceptor(corsInterceptor).addPathPatterns("/**");
}
}
就可以了。
原文章是有
删掉就可以了
- 在shiroConfig中添加
filter的包是
import javax.servlet.Filter;
Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
filters.put("authc", new ShiroUserFilter());
shiroFilterFactoryBean.setFilters(filters);
更新2021.8.18
有评论说没有ShiroUserFilter的代码,已经太久远的程序了,ShiroUserFilter的名字改成OptionalFilter 了
import com.alibaba.fastjson.JSONObject;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.filter.authc.UserFilter;
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;
//使用authc进行权限控制时,若认证不通过,则shiro默认会重定向到loginUrl路径,前端请求接口时会出现302错误
//CORS跨域请求有时发送请求时会预先发送一个OPTIONS请求,不会写到token和参数,这就导致shiro拦截到请求后判定当前用户未登录,从而引发问题
public class OptionalFilter extends UserFilter {
/**
* 在访问过来的时候检查是否为OPTIONS请求,如果是就直接返回true
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
//处理option请求
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpServletRequest httpRequest = (HttpServletRequest) request;
if(httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())){
return true;
}
//单点登录
Subject subject = getSubject(request, response);
//如果 isAuthenticated 为 false 证明不是登录过的,同时 isRemembered 为true 证明是没登陆直接通过记住我功能进来的
if(!subject.isAuthenticated() && subject.isRemembered()){
Session session = subject.getSession();
if(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)!=null){
subject.logout();
}
}
return super.preHandle(httpRequest,httpResponse);
}
/**
* 表示访问拒绝时是否自己处理,如果返回true表示自己不处理且继续拦截执行,返回false表示自己已经处理了
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
response.setContentType("application/json;charset=UTF-8");
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 4020);
jsonObject.put("message", "未登录!");
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
HttpServletRequest httpRequest = (HttpServletRequest) request;
httpServletResponse.setHeader("Access-control-Allow-Origin", httpRequest.getHeader("Origin"));
httpServletResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod());
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers"));
response = httpServletResponse;
response.getWriter().write(jsonObject.toJSONString());
return false;
// return super.onAccessDenied(request, response);
}
}