springboot2+shiro json接口形式处理登录过期重定向https访问是跳转http报错问题

     最近开发一个小项目采用springboot2+shiro前后端分离的方式进行。由于访问使用https证书形式。结果在上线时遇到登录信息过期后shiro设置的跳转接口时重定向为http。从而https访问http报错。网上找了很多都没有一个很好的解决办法。

    一开始想通过redirectHttp10Compatible:解决https环境下使用redirect重定向地址变为http的协议,无法访问服务的问题              设置为false,即关闭了对http1.0协议的兼容支持 ,实际测试不管用。没办法只能重写shiro源码内的方法了。

方法一:重写FormAuthenticationFilter
原理:
假设在shiro.xml中配置了 /** = authc,而默认authc对应org.apache.shiro.web.filter.authc.FormAuthenticationFilter过滤器则表示所有路径都被此过滤器拦截。

第一步:新建一个MyFormAuthenticationFilter类extends FormAuthenticationFilter代码如下:

public class MyFormAuthenticationFilter extends FormAuthenticationFilter {

    private static final Logger log = LoggerFactory.getLogger(MyFormAuthenticationFilter.class);



    @Override
    protected boolean onAccessDenied(ServletRequest request,
                                     ServletResponse response) throws IOException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        Subject subject = getSubject(request, response);
        if (subject.getPrincipal() == null) {
            //设置响应头
            httpResponse.setCharacterEncoding("UTF-8");
            httpResponse.setContentType("application/json");
            //设置返回的数据
            ResultMess resultMess = new ResultMess();
            resultMess.setCode(-10000);
            resultMess.setMsg("未登录");
            resultMess.setSuccess(false);
            Gson gson =  new Gson();
            String result = gson.toJson(resultMess);
            //写回给客户端
            PrintWriter out = httpResponse.getWriter();
            out.write(result);
            //刷新和关闭输出流
            out.flush();
            out.close();
        } else {
            //设置响应头
            System.out.println("=========onAccessDenied==========返回json====>>>>");
            httpResponse.setCharacterEncoding("UTF-8");
            httpResponse.setContentType("application/json");
            //设置返回的数据
            ResultMess resultMess = new ResultMess();
            resultMess.setCode(-10000);
            resultMess.setMsg("未登录");
            resultMess.setSuccess(false);
            Gson gson =  new Gson();
            String s = gson.toJson(resultMess);
            //写回给客户端
            PrintWriter out = httpResponse.getWriter();
            out.write(s);
            //刷新和关闭输出流
            out.flush();
            out.close();
        }
        return false;
    }
}

第二步:ShiroConfig 类中将重写的MyFormAuthenticationFilter赋予ShiroFilterFactoryBean 代码如下:

@Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
//        shiroFilterFactoryBean.setLoginUrl("/adminUser/unauth");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/");
        // 未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/adminUser/unauth");
        Map filtersMap = new HashMap<>();
        MyFormAuthenticationFilter authFilter = new MyFormAuthenticationFilter();
        filtersMap.put("authc", authFilter);
        shiroFilterFactoryBean.setFilters(filtersMap);

        // 配置数据库中的resource
        Map filterChainDefinitionMap = shiroService.loadFilterChainDefinitions();
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

第三步:

将所以的需要拦截的标注为authc,次处的authc和filtersMap.put("authc", authFilter);设置的对应。

这样shiro判断到未登录就进入次拦截器,返回json数据给前端避免了重定向url.

你可能感兴趣的:(springboot,springboot,shiro,https转http)