方法一:
/**
* @author 李晨亮
* @date 2020-07-31 17:08
**/
@Component
public class MyHttpAuthenticationFilter extends BasicHttpAuthenticationFilter {
// /**
// * 对跨域提供支持
// */
// @Override
// protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
// HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin")); //标识允许哪个域到请求,直接修改成请求头的域
// httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");//标识允许的请求方法
// // 响应首部 Access-Control-Allow-Headers 用于 preflight request (预检请求)中,列出了将会在正式请求的 Access-Control-Expose-Headers 字段中出现的首部信息。修改为请求首部
// httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
// //给option请求直接返回正常状态
// if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
// httpServletResponse.setStatus(HttpStatus.OK.value());
// return false;
// }
// return super.preHandle(request, response);
// }
}
方法二通过过滤器处理跨域问题:
第一步先提前实现ShiroFilterFactoryBean:
设置自定义的过滤器, 配置过滤器,跨域访问时,对OPTIONS的请求返回true,这个很重要,不然不能获取header上的值
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 设置自定义的过滤器, 配置过滤器,跨域访问时,对OPTIONS的请求返回true,这个很重要,不然不能获取header上的值
Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
filters.put("authc", new CustomFormAuthenticationFilter());
filters.put("perms", new CustomPermissionsAuthorizationFilter());
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//注意过滤器配置顺序 不能颠倒
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了,登出后跳转配置的loginUrl
filterChainDefinitionMap.put("/user/logout", "logout");
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/user/ajaxLogin", "anon");
filterChainDefinitionMap.put("/user/login", "anon");
//pdf授权访问路径对外打开
filterChainDefinitionMap.put("/fession/ossauth", "anon");
// 上传图片和视频
filterChainDefinitionMap.put("/ueditor/getConfig", "anon");
filterChainDefinitionMap.put("/article/getUploadImgUrl", "anon");
filterChainDefinitionMap.put("/article/getUploadAdviceUrl", "anon");
// 查询数据库权限配置
List<SysResource> resourceList = sysResourceDao.selectAllResource(CoreConstant.AVAILABLE_NORMAL);
for (SysResource sysResource : resourceList) {
String path = sysResource.getPath();
String permission = sysResource.getPermission();
if (StringUtils.isNotBlank(path) && StringUtils.isNotBlank(permission)) {
String perm = "perms[" + permission + "]";
filterChainDefinitionMap.put(path, perm);
}
}
filterChainDefinitionMap.put("/**", "authc");
//配置shiro默认登录界面地址,前后端分离中登录界面跳转应由前端路由控制,后台仅返回json数据
shiroFilterFactoryBean.setLoginUrl("/user/login");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
**
* 自定义认证过滤器
*
* @date 2020/7/24 15:54
*/
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {
/**
* 屏蔽OPTIONS请求
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
boolean accessAllowed = super.isAccessAllowed(request, response, mappedValue);
if (!accessAllowed) {
// 判断请求是否是options请求
String method = WebUtils.toHttp(request).getMethod();
if (StringUtils.equalsIgnoreCase("OPTIONS", method)) {
return true;
}
}
return super.isAccessAllowed(request, response, mappedValue);
}
/**
* 解决未登录302问题
*如果shiro没有缓存到的路径是走这里
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
return executeLogin(request, response);
} else {
return true;
}
} else {
// 返回固定的JSON串
WebUtils.toHttp(response).setContentType("application/json; charset=utf-8");
WebUtils.toHttp(response).getWriter().print(JSONObject.toJSONString(new Result<>().fali("未登录")));
return false;
}
}
}
**
* 自定义权限过滤器
*
* @date 2020-07-24 15:05
**/
public class CustomPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {
/**
* 屏蔽OPTIONS请求
*
* @param request
* @param response
* @param mappedValue
* @return
* @throws IOException
*/
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
// 判断请求是否是options请求
String method = WebUtils.toHttp(request).getMethod();
if (StringUtils.equalsIgnoreCase("OPTIONS", method)) {
return true;
}
return super.isAccessAllowed(request, response, mappedValue);
}
/**
* 解决权限不足302问题
* 如果shiro没有缓存到的路径是走这里
*
* @param request
* @param response
* @return
* @throws IOException
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
Subject subject = getSubject(request, response);
if (subject.getPrincipal() == null) {
saveRequestAndRedirectToLogin(request, response);
} else {
WebUtils.toHttp(response).setContentType("application/json; charset=utf-8");
WebUtils.toHttp(response).getWriter().print(JSONObject.toJSONString(new Result<>().fali("无权限")));
}
return false;
}
}