前后端分离项目中后台集成shiro需要注意的二三事

1. 修改 Shiro 认证失败后默认重定向处理问题

  a. 继承需要使用的 ShiroFilter,重载 onAccessDenied() 方法:

  @Override
  protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
    Response result = Response.SUCCESS;
    result.setCode(EReturnCode.UNAUTHENTICATED.code());
    result.setMsg(EReturnCode.UNAUTHENTICATED.message());
    Gson gson = new Gson();
    String json = gson.toJson(result);
    HttpServletResponse httpServletResponse
= (HttpServletResponse) response;     httpServletResponse.getWriter().write(json);     return false;   }

  b. 在 Shiro 配置类中使用自定义配置:

  /*
   * 1.定义ShiroFilterFactoryBean
   */
  ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
  // 2.注册SecurityManager
  shiroFilterFactoryBean.setSecurityManager(securityManager);
  // 3.配置拦截器
  Map<String, Filter> filterMap = new LinkedHashMap();
  // 配置user拦截
  filterMap.put("user", new ShiroUserFilter());
  // 配置authc拦截
  filterMap.put("authc", new ShiroAuthenticationFilter());
  shiroFilterFactoryBean.setFilters(filterMap);

2. 跨域及 cookie 丢失问题

  a. 前端创建 axios 实例时添加配置:

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_BACKGROUND, // url = base url + request url
  withCredentials: true, // send cookies when cross-domain requests
  crossDomain: true,
  timeout: 5000 // request timeout
})

  b. 后端配置 CorsFilter 过滤器处理跨域问题,添加如下配置并把过滤器优先级调高

  /**
     * 为response设置header,实现跨域
     *
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;

        // 指定本次预检请求的有效期,单位为秒
        response.setHeader("Access-Control-Max-Age", "1800");
        // 防止乱码,适用于传输JSON数据
        response.setHeader("Content-Type","application/json;charset=UTF-8");
        // 跨域的header设置
        String method = request.getMethod();
        response.setHeader("Access-Control-Allow-Methods", method);
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));

        // 在访问过来的时候检测是否为OPTIONS请求,如果是就直接返回true(解决cookie丢失问题)
        if ("OPTIONS".equalsIgnoreCase(method)) {
            servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
        } else {
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

参考文章:

  https://www.cnblogs.com/chinaifae/p/10189312.html Access-Control-Max-Age 和 OPTION请求

  https://blog.csdn.net/madonghyu/article/details/80027387 OPTION导致cookie丢失

  https://blog.csdn.net/fifteen718/article/details/81127782 前后端分离传递cookie配置

  https://blog.csdn.net/yao_1996/article/details/83510474 前后端分离传递sessionId

  https://segmentfault.com/q/1010000019774772 其它问题

原文地址:https://www.cnblogs.com/tarencez/p/11724781.html