前后端分离项目SpringBoot-Shiro-jwt处理401响应码的方案

news2024/11/22 16:06:40

问题现象:

现在大多数项目已经实现前后端分离,当采用shiro作为安全框架时,如果请求的token已过期或未认证请求,会得到401的HTTP STATUS。此时在前端还会因为401的错误弹出一个登录认证的弹框。效果如下:

 经分析,浏览器弹出该弹框,主要是由于请求头中包含了:

WWW-Authenticate: BASIC realm="application"

当客户端(浏览器)收到带有类似“WWW-Authenticate: Basic realm=“.””的信息后,将会弹出一个对话框,要求用户输入验证信息。在实际项目中我们可能不希望浏览器帮助做登录认证,而是希望返回到自己的登录页面。

问题分析:

首先分析为什么后台会返回401和在response header中添加WWW-Authenticate: BASIC realm="application"。这些可能在项目代码中压根都找不到的东西。这段东西的源码在:

org.apache.shiro.web.filter.authc.HttpAuthenticationFilter

中,详细截图如下:

    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        boolean loggedIn = false;
        if (this.isLoginAttempt(request, response)) {
            loggedIn = this.executeLogin(request, response);
        }

        if (!loggedIn) {
            this.sendChallenge(request, response);
        }

        return loggedIn;
    }

 上边的方法是访问拒绝处理的逻辑,​ isLoginAttempt(),该方法前面已经出现,通过请求头判断是否为尝试登陆,如果 true,则执行登录逻辑;反之,sendChallenge

    protected boolean sendChallenge(ServletRequest request, ServletResponse response) {
        log.debug("Authentication required: sending 401 Authentication challenge response.");
        HttpServletResponse httpResponse = WebUtils.toHttp(response);
        httpResponse.setStatus(401);
        String authcHeader = this.getAuthcScheme() + " realm=\"" + this.getApplicationName() + "\"";
        httpResponse.setHeader("WWW-Authenticate", authcHeader);
        return false;
    }

解决办法:

其实看到上边的源码之后,解决办法就差不多有了。那就是把

onAccessDenied

方法重写,让他走我们自己实现的方法。本文主要介绍JWT的解决办法。shiro+jwt通常都会自定义一个

JwtFilter extends BasicHttpAuthenticationFilter

看见了吧,这就是重点。既然继承了,那么当然可以重写父类的方法。至于怎么重写,写成什么样就根据自己的需求来了。本篇文章介绍另外一种方法,不重写onAccessDenied方法。

1、首先我们在JwtFilter中自定义一个401状态码的处理方法

    /**
     * 将非法请求跳转到 /401
     */
    private void response401(ServletRequest req, ServletResponse resp) {
        try {
            HttpServletResponse httpServletResponse = (HttpServletResponse) resp;
            httpServletResponse.sendRedirect("/401");
        } catch (IOException e) {
            LOGGER.error(e.getMessage());
        }
    }

2、在JwtFilter中一般有isAccessAllowed方法,里边会有认证失败的处理逻辑,我们把处理401请求的方法放到里边,实例如下:

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        if (isLoginAttempt(request, response)) {
            try {
                executeLogin(request, response);
            } catch (Exception e) {
                response401(request, response);
            }
        }
        return true;
    }

3、然后搞个专门处理/401的接口,示例如下:

    @RequestMapping(path = "/401")
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public Result unauthorized() {
        return ResultUtils.success(401, "未授权", null);
    }

4、最后配一下把所有未认证的请求转发到我们自定义的401接口上,配置如下:

 @Bean("shiroFilter")
    public ShiroFilterFactoryBean factory(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();

        // 添加自己的过滤器并且取名为jwt
        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put("jwt", new JWTFilter());
        factoryBean.setFilters(filterMap);

        factoryBean.setSecurityManager(securityManager);
        factoryBean.setUnauthorizedUrl("/401");

        /*
         * 自定义url规则
         * http://shiro.apache.org/web.html#urls-
         */
        Map<String, String> filterRuleMap = new HashMap<>();
        // 所有请求通过我们自己的JWT Filter
        filterRuleMap.put("/**", "jwt");
        // 访问401和404页面不通过我们的Filter
        filterRuleMap.put("/401", "anon");
        factoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return factoryBean;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/615383.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DataLeap的全链路智能监控报警实践(一):常见问题

随着字节跳动业务的快速发展&#xff0c;大数据开发场景下需要运维管理的任务越来越多&#xff0c;然而普通的监控系统只支持配置相应任务的监控规则&#xff0c;已经不能完全满足当前需求&#xff0c;在日常运维中开发者经常会面临以下几个问题&#xff1a; 任务多&#xff0c…

凝聚全球顶尖力量,助力开源行业发展 | 2023开放原子全球开源峰会开幕式暨高峰论坛亮点抢先看!

亮点攻略 一触即发 6月11-13日&#xff5c;中国北京 作为开源领域一年一度的盛事&#xff0c;由2023全球数字经济大会组委会主办&#xff0c;开放原子开源基金会、北京市经济和信息化局、北京经济技术开发区管理委员会承办的2023开放原子全球开源峰会将于6月11日至13日在北京…

实现Mac使用空格键预览更多文件格式

mac上的快速预览非常好用&#xff0c;但是对于许多格式的不支持造成了体验感的割裂。例如对于使用频繁的.md、.js、.py等格式的文件&#xff0c;无法生成缩略图。可以通过在「Quick Look」中 安装插件的方式来实现预览格式的扩展。 1. 插件的安装 下载的插件一般有两种格式&am…

SpringBoot的高考志愿填报系统(含源码+数据库)

系统获取方式&#xff1a; 1.系统分析 在本系统中&#xff0c;基于SpringBoot的高考志愿填报系统需要满足以下功能需求&#xff1a; 1.用户可以根据自己的院校类型、办学类型、层次类型、地域等因素筛选高校。 2.用户可以查询到所选高校的基本信息&#xff0c;包括学校的概况…

vcsa6.7更换证书

今天一早&#xff0c;有现场反馈&#xff0c;vcenter无法登录&#xff0c;估计到可能是证书到期了 在浏览器中确认下&#xff0c;确实是证书到期的问题 通过查看你sts不过期&#xff0c;直接更新全部证书 To escape to local shell, press CtrlAlt]. VMware vCenter Server Ap…

翻车了,lombok这玩意真坑

目录 背景排查Setter-Getter方法的坑解决原因解决方案原因解决方案 总结 背景 青柠最近在写自己的项目&#xff0c;刚开始就写不下去了&#xff0c;心态崩了&#xff0c;这啥玩意啊&#xff0c;就是找不到问题在哪&#xff1f; 早前&#xff0c;在项目当中引入了Lombok插件&a…

zabbix配置监控日志

目录 一、zabbix日志监控的功能 二、zabbix监控日志的条件 三、日志监控的监控指标 四、日志监控Item的配置案例 一、zabbix日志监控的功能 Zabbix-agent支持对日志文件的监控&#xff0c;可以对日志对的关键字进行监控&#xff0c;然后告警。日志监控支持普通的日志文件&am…

ChatGPT与软件架构(5) - 网络安全

安全是任何系统都无法回避的关键要素&#xff0c;本文介绍了若干利用ChatGPT增强的网络安全攻击&#xff0c;并提出了应对策略。原文: ChatGPT and Cyber Security Benjamin Elliott Unsplash 如果你还不熟悉ChatGPT&#xff0c;那么考虑到这种生成式人工智能服务的快速崛起&am…

Hive SQL 语法大全~

基于语法描述说明 CREATE DATABASE [IF NOT EXISTS] db_name [LOCATION] path; SELECT expr, ... FROM tbl ORDER BY col_name [ASC | DESC] (A | B | C) 如上语法&#xff0c;在语法描述中出现&#xff1a; []&#xff0c;表示可选&#xff0c;如上[LOCATION]表示可写、可不…

神州数码DCRS试题题目合集

2017.11.3 DCRS 在公司总部的DCRS上配置&#xff0c;配置设备enable密码&#xff0c;并且在登录设备时必须正确输入enable密码才能进入交换机的配置模式。 在公司总部的DCRS上配置&#xff0c;在交换设备上开启SSH管理功能&#xff0c;用户名和密码都是DCN&#xff0c;并关闭…

flutter系列之:做一个会飞的菜单

文章目录 简介定义一个菜单项目让menu动起来添加菜单内部的动画总结 简介 flutter中自带了drawer组件&#xff0c;可以实现通用的菜单功能&#xff0c;那么有没有一种可能&#xff0c;我们可以通过自定义动画来实现一个别样的菜单呢&#xff1f; 答案是肯定的&#xff0c;一起…

(栈和队列) 150. 逆波兰表达式求值 ——【Leetcode每日一题】

❓150. 逆波兰表达式求值 难度&#xff1a;中等 给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意&#xff1a; 有效的算符为 ‘’、‘-’、‘*’ 和 ‘/’ 。每个操作数&#…

vue制作自己的组件库(仿ElementUI)

1.首先自己创建个新的vue项目&#xff0c;之后更改下目录形式&#xff0c;将src文件更改为examples&#xff0c;这里是专门放组件展示的md文件&#xff0c;packages文件里是放自己写的组件代码 2.然后是开始配置vue.config.js文件 &#xff0c;其中md-loader是读取md文件的相关…

Linux下安装docker教程

目录 一、安装CentOS系统 二、安装Docker 1.卸载之前安装过的旧版本&#xff1a; 2.安装docker 3.启动docker 4.配置docker镜像仓库 三、Docker的使用 1.docker容器常用指令&#xff1a; 2.运行案例&#xff1a;docker拉取并运行nignx 3.查看容器日志 一、安装CentOS系…

Prompt工程-高级提示

高阶Prompting 到这一步&#xff0c;应该很明显&#xff0c;改进提示有助于在不同任务上获得更好的结果。这就是Prompt工程背后的整个理念。 虽然之前的例子很有趣&#xff0c;但在我们深入了解更高级的概念之前&#xff0c;让我们先正式地介绍一些概念。 文章目录 高阶Promp…

使用Flexible实现移动端页面的终端适配,及快捷设置开发工具px转换rem

1、使用Flexible实现移动端页面的终端适配 官网GitHub地址API介绍&#xff1a; ​​​​​​使用Flexible实现手淘H5页面的终端适配 Issue #17 amfe/article GitHub 阿里 cdn 引入地址&#xff1a; <script src"http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??…

JavaWeb公司员工管理系统

1.需求分析 系统角色分别为&#xff1a;最高权限管理员、人力主管、部门主管、员工。总体业务流程图如下图所示。 用例图如下所示。 2.系统设计 系统功能总体设计如下图。 数据库设计如下图所示。 3.系统实现效果 登录功能实现效果如下图所示。 考勤管理模块实现效…

字节同事问我:我的Postman为什么连不了数据库?

postman本身没有数据库连接功能&#xff0c;所以用到了node.js中的xmysql实现Rest API的生成&#xff0c;利用postman进行请求&#xff0c;获取需要的数据&#xff0c;来做数据准备或断言 1 安装 安装node.js&#xff1a;要求版本大于等于7.6 首先保证你的环境上有node.js&…

云计算基础

一、分布式计算 分布式计算将应用分解成许多更小的部分&#xff0c;分配到多台计算机进行处理&#xff0c;这样可以节省整体计算时间&#xff0c;大大提高计算效率。 云计算是分布式计算技术的一种&#xff0c;也是分布式计算这种科学概念的商业实现。分布式计算的优点就是发…

chatgpt赋能python:Python如何分割列表

Python如何分割列表 介绍 在Python编程中&#xff0c;列表是一种非常常见的数据类型。有时候我们需要将一个大的列表分割成几个小的列表&#xff0c;以便更好地处理数据。Python提供了多种方法来实现这个目的。在本文中&#xff0c;我们将介绍Python中如何分割列表的几种方法…