• SpringBoot整合Shiro前后端分离在Https环境下登陆失效的问题


    最近在项目上线的时候遇到了个问题,就是SpringBoot整合Shiro前后端分离在Https环境下登陆失效的问题。返回的结果是302。

    错误的原因是,在https的环境内,限制http,而在Shiro框架内置的用户登陆校验,在校验失败后会保存当前请求,然后重定向到登陆页面(因为是前后端分离,我这里跳转的登录页直接就是401的JSON,通知前端进行跳转)。Shiro内部重定向的请求是http,所以请求异常。具体源码在下面:

    FormAuthenticationFilter:

    AccessControlFilter:

    具体是不是这个兼容HTTP1.0的默认值的问题,还不好说,因为重写这个方法改为false也没有效果。

     所以,下面提供了两个解决方案:

    这里因为是前后端分离,所以原本就有一个解决涉及到预请求OPTIONS没有权限影响到跨域的过滤器。所以就直接在这个过滤器上进行改动了,如果没有的,原本没有过滤器的可以添加一个。

    通过重写onAccessDenied方法。

    解决方案1:直接抛出异常,让我们全局的异常捕捉,返回登陆提示。

    解决方案2:直接返回登陆提示。不进行后续的转发操作。

    1. public class CorsAuthenticationFilter extends FormAuthenticationFilter {
    2. @Override
    3. protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
    4. boolean allowed = super.isAccessAllowed(request, response, mappedValue);
    5. // 提示OPTIONS预检时,后端需要设置的两个常用自定义头
    6. HttpServletResponse httpServletResponse = (HttpServletResponse)response;
    7. httpServletResponse.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
    8. if (!allowed) {
    9. // 判断请求是否是options请求
    10. String method = WebUtils.toHttp(request).getMethod();
    11. if (StringUtils.equalsIgnoreCase("OPTIONS", method)) {
    12. return true;
    13. }
    14. }
    15. return allowed;
    16. }
    17. @Override
    18. protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
    19. if (isLoginRequest(request, response)) {
    20. if (isLoginSubmission(request, response)) {
    21. return executeLogin(request, response);
    22. } else {
    23. return true;
    24. }
    25. } else {
    26. //解决方案1:直接抛出异常,异常会被捕获处理
    27. //throw new UnauthenticatedException();
    28. //解决方案2:在这里进行返回,不抛出异常,也不进行跳转
    29. response.setCharacterEncoding("UTF-8");
    30. response.setContentType("application/json");
    31. //获取会话
    32. Subject subject = getSubject(request, response);
    33. if (subject.getPrincipal() == null) {
    34. //写回给客户端
    35. PrintWriter out = response.getWriter();
    36. out.write(JSONUtil.objectToJson(RestStatus.createByError(ResultCodeEnum.INVALID_USER)));
    37. //刷新和关闭输出流
    38. out.flush();
    39. out.close();
    40. }
    41. return false;
    42. }
    43. }
    44. }

    然后配置下这个过滤器,这个过滤器,只作用于需要登陆的接口。

    1. @Bean
    2. public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
    3. ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    4. //设置安全管理器
    5. shiroFilterFactoryBean.setSecurityManager(securityManager);
    6. // 修改调整的登录页面
    7. shiroFilterFactoryBean.setLoginUrl("/page/401");
    8. // 登录成功后要跳转的链接
    9. shiroFilterFactoryBean.setSuccessUrl("/page/index");
    10. // 未授权提示页面
    11. shiroFilterFactoryBean.setUnauthorizedUrl("/page/403");
    12. Map filters = shiroFilterFactoryBean.getFilters();
    13. filters.put("shiroCorsFilter", new CorsAuthenticationFilter());
    14. //拦截器
    15. Map filterChainDefinitionMap = new LinkedHashMap<>();
    16. //带api路由的所有请求全部要求登陆
    17. filterChainDefinitionMap.put("/api/**", "shiroCorsFilter");
    18. //其他的所有请求放行
    19. filterChainDefinitionMap.put("/**", "anon");
    20. shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    21. return shiroFilterFactoryBean;
    22. }

    这样就解决了问题。如果能给诸位带来帮助,麻烦点个赞。

  • 相关阅读:
    字符串转为 double 类型
    【IMX6ULL笔记】-- 从驱动到应用(基于Qt)- LED
    微型计算机原理2
    什么是短网址?如何调用接口生成短地址?
    孩子升年级难适应?猿辅导语文金牌教研来支招
    Node 基础
    基于Matlab利用IRM和RRTstar实现无人机路径规划(附上源码+数据+说明+报告+PPT)
    【visionOS】从零开始创建第一个visionOS程序
    一般PMP证书会被认为是比较可靠的认证吗?Hr怎么看待?
    【PyTorch深度学习项目实战100例】—— 基于Transformer实现电影评论星级分类任务 | 第42例
  • 原文地址:https://blog.csdn.net/qq826303461/article/details/126173125