问题:

集成shiro之后发现配置放行的接口可以正常访问,而需要登录验证的接口会报错

其中OPTIONS类型的接口会报302

导致后续的post请求报错提示跨域问题


Shiro登录流程

首先Shiro是根据请求中cookie携带的JSESSIONID判断是否登录的
当调用登录接口登录成功时,后端的响应头会添加一个set-cookie的参数
JSESSIONID代表当前登录的用户,前端只要在请求中携带这个参数Shiro就可以识别出用户并放行。
但是post请求会先发送一个OPTIONS类型的探测请求,由于这个请求没有携带JSESSIONID,Shiro就会判断为未登录,进行拦截。
所以解决的思路就是放行OPTIONS类型的请求。

解决

  1. 创建ShiroUserFilter
package com.school.service.config;import com.school.service.entity.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.authc.UserFilter;
import org.springframework.context.annotation.Configuration;
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;@Slf4j
public class ShiroUserFilter extends UserFilter {/*** 在访问过来的时候检测是否为OPTIONS请求,如果是就直接返回true*/@Overrideprotected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {HttpServletResponse httpResponse = (HttpServletResponse) response;HttpServletRequest httpRequest = (HttpServletRequest) request;if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {log.info("OPTIONS放行");setHeader(httpRequest,httpResponse);return true;}return super.preHandle(request,response);}/*** 该方法会在验证失败后调用,这里由于是前后端分离,后台不控制页面跳转* 因此重写改成传输JSON数据*/@Overrideprotected void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException {saveRequest(request);setHeader((HttpServletRequest) request,(HttpServletResponse) response);PrintWriter out = response.getWriter();//自己控制返回的json数据out.println(new Result("500",null,"Shiro验证失败"));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());}
}
  1. 在Shiro配置类的shiroFilter中添加进去
package com.school.service.config;import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;/*** Shiro配置类*/
@Configuration
public class ShiroConfig {@Bean(name = "shiroFilter")public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager);shiroFilterFactoryBean.setLoginUrl("/school/goToLogin");//设置登录页面shiroFilterFactoryBean.setUnauthorizedUrl("/school/goToLogin");//权限不足跳转页面,这个在Default过滤器中设置无效,具体看 https://blog.csdn.net/bicheng4769/article/details/86680955//添加自定义Filter,放行OPTIONS请求-----------------------------------------这里✨✨✨✨✨✨✨✨Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();filters.put("authc", new ShiroUserFilter());shiroFilterFactoryBean.setFilters(filters);//----------------------------------------------------------------------------------------------✨Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->filterChainDefinitionMap.put("/service/school/**", "anon");filterChainDefinitionMap.put("/swagger-ui.html", "anon");filterChainDefinitionMap.put("/swagger-resources", "anon");filterChainDefinitionMap.put("/v2/api-docs", "anon");filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/**", "anon");filterChainDefinitionMap.put("/configuration/security", "anon");filterChainDefinitionMap.put("/configuration/ui", "anon");filterChainDefinitionMap.put("/service/article/**", "authc");filterChainDefinitionMap.put("/service/chat/**", "authc");filterChainDefinitionMap.put("/service/diary/**", "authc");filterChainDefinitionMap.put("/service/file/**", "authc");filterChainDefinitionMap.put("/service/problem/**", "authc");filterChainDefinitionMap.put("/service/team-article/**", "authc");filterChainDefinitionMap.put("/service/team/**", "authc");filterChainDefinitionMap.put("/service/user/**", "authc");filterChainDefinitionMap.put("/service/user-friend/**", "authc");filterChainDefinitionMap.put("/service/user-info/**", "authc");filterChainDefinitionMap.put("/service/widget/**", "authc");//主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 剩余的都需要认证filterChainDefinitionMap.put("/**", "anon");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactoryBean;}@Beanpublic SecurityManager securityManager(){DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();defaultWebSecurityManager.setRealm(myRealm());return defaultWebSecurityManager;}@Beanpublic MyRealm myRealm (){MyRealm myRealm = new MyRealm();return myRealm;}}

一切正常

SpringBoot+Shiro放行OPTIONS请求,解决跨域问题相关推荐

  1. 继承WebMvcConfigurer 和 WebMvcConfigurerAdapter类依然CORS报错? springboot 两种方式稳定解决跨域问题

    继承WebMvcConfigurer 和 WebMvcConfigurerAdapter类依然CORS报错???springboot 两种方式稳定解决跨域问题! 之前我写了一篇文章,来解决CORS报错 ...

  2. springboot中通过cors协议解决跨域问题

    2019独角兽企业重金招聘Python工程师标准>>> 1.对于前后端分离的项目来说,如果前端项目与后端项目部署在两个不同的域下,那么势必会引起跨域问题的出现. 针对跨域问题,我们可 ...

  3. React Axios 请求解决跨域问题

    网上看了很多的方案,但是不知道为什么,作为初学者,对react不太清楚的话,解决跨域还是有很多的问题.这篇博客针对小白,第一次调试react 跨域问题,甚至第一次使用Axios ,第一次... 废话就 ...

  4. AJAX异步请求解决跨域问题的三种方式

    一 什么是跨域 出于浏览器的同源策略限制.同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说We ...

  5. springboot入门demo详解(解决跨域)

    前言: 微服务自问世以来就一直很火.天天耳听Springboot,Springcloud,docker,这些名词,以前没学Springboot的时候刚学ssm的时候,,说实话头都炸了.单独一个个学习S ...

  6. uni-app之网络请求解决跨域

    一:uniapp网络请求 第一步:新建uni-app项目 第二步:在npmjs中下载第三方包(用于请求) 安装步骤链接如下: @escook/request-miniprogram - npm 1.打 ...

  7. options请求(跨域预检)

    概述 options 请求就是预检请求,可用于检测服务器允许的 http 方法.当发起跨域请求时,由于安全原因,触发一定条件时浏览器会在正式请求之前自动先发起 OPTIONS 请求,即 CORS 预检 ...

  8. 【原创】OPTIONS请求之跨域请求被阻止(原因:CORS预检通道未成功)解决方案 超神!牛逼!

    问题详情 Stackoverflow:OPTIONS请求跨域问题https://stackoverflow.com/questions/72465838/why-does-this-cors-pref ...

  9. Nginx 反向代理解决跨域问题

    目录 前言 Nginx 反向代理常用配置 Server location proxy_pass add_header OPTIONS 请求 proxy_set_header 跨域的 cookie 传输 ...

最新文章

  1. linux常用的28个快捷键
  2. 斯坦福NLP笔记72 —— The Inverted Index
  3. 学C++,80%都是为了搞竞赛、凑一门语言?网友:莫钓鱼
  4. convexHull函数
  5. linux C语言 socket编程教程(附两个例子)(socket教程)
  6. dll 和 lib--初级
  7. Mysql能删了重装吗_mysql卸载重新安装
  8. 基于modelsim-SE的简单仿真流程—上
  9. 测试工程师python面试常问问题_面试测试工程师一般会问些什么?
  10. 如何下载python3.6版本-python最新版本免费下载-python 3.6.3正式版下载__飞翔下载
  11. rmarkdown+flexdashboard制作dashboard原型
  12. Win10加Ubuntu20.04双系统安装教程
  13. azkaban 项目依赖
  14. Best Android Remote Desktop Apps?
  15. 一个故事轻松记忆常见252个英语字根(1~30)
  16. 新闻丨5G牌照发布,智链万源携手动物健康与食品安全创新联盟在农业领域先声夺人...
  17. Gitee 图床被屏蔽后,我搭建了一个文件系统并封装成轮子开源
  18. 内卷老员工之java内存模型的happens-before原则
  19. dba_autotask_client
  20. 常见的web网络攻击处理方案

热门文章

  1. vbS访问mysql语句_关于VBS连接MySQL与连接Excel
  2. java水仙花数代码_java知识分享篇(五)
  3. transform 二维转变
  4. 3.9 限制root远程登录
  5. 数据分析,怎么做才算到位?
  6. 【数据结构笔记12】平衡二叉树,AVL树,RR旋转/LL旋转/LR旋转/RL旋转,AVL树插入的代码实现
  7. virtualmin修改php.ini,virtualmin安装和配置使用
  8. 大数据催生智慧园区_杭州经纬智慧园区如何实现各系统间信息数据集中关联、一站管控...
  9. html5作品分析报告,性能报告之HTML5 性能测试报告
  10. linux安装完mysql后如何初始化,linux yum安装mysql后要注意的一些初始化问题linux服务器应用 -电脑资料...