自定义过滤器配置 Shiro 认证失败返回 json 数据

这篇具有很好参考价值的文章主要介绍了自定义过滤器配置 Shiro 认证失败返回 json 数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

by emanjusaka from ​ https://www.emanjusaka.top/2023/10/filter-shiro-authentication-error-json 彼岸花开可奈何
本文欢迎分享与聚合,全文转载请留下原文地址。

Shiro权限框架认证失败默认是重定向页面的,这对于前后端分离的项目及其不友好,可能会造成请求404的问题。现在我们自定义过滤器实现认证失败返回json数据。

拦截器就是一道道的关卡,每一道关卡都有各自的职责。

实现思路

由于Shiro默认的过滤器认证失败后是进行重定向操作的,所以我们考虑自定义过滤器重写它的逻辑。

  1. 设置 ShiroShiroFilterFactoryBean拦截请求进行认证并配置自定义的拦截器。

  2. 实现自定义的拦截器,重写认证失败后的逻辑。

实现过程

  1. 配置 ShiroShiroFilterFactoryBean设置拦截请求进行认证

    @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            Map<String, String> map = new LinkedHashMap<>();
            //登出
            map.put("/logout", "logout");
            // 登录
            map.put("/login","anon");
            //对所有用户认证
            map.put("/**", "authc");
            Map<String, Filter> filterMap = new HashMap<>();
            // 自定义的拦截器
            filterMap.put("authc",new ShiroLoginFilter());
            shiroFilterFactoryBean.setFilters(filterMap);
            shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
            return shiroFilterFactoryBean;
        }
    

上面配置对登录接口进行了放行,对其他接口都要进行认证,这个可以根据自己的实际需要去配置。同时还要配置我们的自定义拦截器,拦截器Map 的key要和配置的认证authc一致,否则会不生效。

  1. 实现自定义的拦截器,重写认证失败后的逻辑。

    package com.icms.shiro.filter;
    
    import com.alibaba.fastjson.JSON;
    import com.icms.enu.ExceptionCodeEnum;
    import com.icms.exception.CustomException;
    import com.icms.page.Result;
    import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
    import org.camunda.bpm.model.bpmn.impl.instance.From;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.PrintWriter;
    
    /**
     * @Author emanjusaka
     * @Date 2023/10/25 14:42
     * @Version 1.0
     */
    public class ShiroLoginFilter extends FormAuthenticationFilter {
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            httpResponse.setStatus(200);
            httpResponse.setContentType("application/json;charset=utf-8");
            //解决跨域问题
            if ("OPTIONS".equals(httpRequest.getMethod())){
                httpResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);;
                return true;
            }
            httpResponse.getWriter().print(JSON.toJSONString(new Result(ExceptionCodeEnum.STATUS_CODE_NO_LOGIN)));
            httpResponse.getWriter().flush();
            httpResponse.getWriter().close();
            return false;
        }
    }
    
    

    这里自定义拦截器继承FormAuthenticationFilter 重写了 onAccessDenied 方法。在onAccessDenied 方法中我们可以返回我们需要的 json 数据,也可以记录日志执行我们自己的方法。这里返回的数据是我自定义的Result 类,里面包含了错误码和错误信息。

    认证失败是我们的业务逻辑的错误而不是网络请求的错误,所以我们把HTTP的状态码设置成了 200 ,通过我们自己定义的Result来返回实际的错误信息。

    注意:Shiro本身是没有解决跨域问题的,我们要自己实现解决Shiro的跨域问题。

    例如/user/getUserInfo接口,没有配置过滤,就会被拦截,这个时候无论是在Controller上还是在接口实现上配置@CrossOrigin,都不会生效。这个时候需要做如下配置:

    //解决跨域问题
            if ("OPTIONS".equals(httpRequest.getMethod())){
                httpResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
                return true;
            }
    

    自己实现拦截器设置允许跨域也是可以的,这里使用的上述的方法。

扩展知识

Shiro中的拦截器

  1. authc拦截器:主要用于实现基于表单的身份验证,它会拦截用户登录表单提交的路径,并在拦截器工厂中配置该路径。此外,它负责创建登录认证所需的Token令牌,并触发登录认证流程。如果用户已经登录,那么将直接进入要访问的路径;如果用户未登录,则访问会被拒绝,并自动跳转到登录页面。

  2. authcBasic拦截器:主要用于实现基于HTTP基本认证的身份验证。

  3. logout拦截器:主要用于处理用户的注销请求。

  4. user拦截器:充当了整个安全管理器的入口,主要负责拦截需要安全控制的请求并进行处理。

  5. anon拦截器:这种拦截器允许不需要登录就能访问的资源,通常用于静态资源或者移动端接口。

  6. roles拦截器:主要负责用户的角色校验。

  7. perms拦截器和roles拦截器:这两个拦截器主要与授权相关,用于处理用户角色和权限相关的请求。

  8. port拦截器:它主要拦截网络请求,验证用户是否具有访问特定端口的权限。

  9. rest拦截器:用于在Web应用程序中对HTTP请求的请求方法(HTTP method)进行权限过滤和控制。它的作用是限制用户对某些HTTP请求方法的访问权限,例如GET、POST、PUT、DELETE等。通过该过滤器,您可以根据需要来控制某些请求方法的访问权限,并且可以根据不同的请求方法,对不同的用户或用户组进行特定的授权设置。

  10. ssl拦截器:主要用于处理SSL协议相关的请求。

  11. noSessionCreation拦截器:用于处理无状态会话的过滤器。

public enum DefaultFilter{
  anno(AnonymousFilter.class),
  authc(FormAuthenticationFilter.class),
  authcBasic(BasicHttpAuthenticationFilter.class),
  logout(LogoutFilter.class),
  noSessionCreation(NoSessionCreationFilter.class),
  perms(PermissionsAuthorizationFilter.class),
  port(PortFilter.class),
  rest(HttpMethodPermissionFilter.class),
  roles(RolesAuthorizationFilter.class),
  ssl(SslFilter.class),
  user(UserFilter.class);
}

与身份验证相关的拦截器

  • authc(FormAuthenticationFilter)

    基于表单的拦截器;如“/**=authc”,如果没有登录会跳转到相应的登录页面登录。
    主要属性:
    usernameParam:表单提交的用户名参数名(username)。
    passwordParam:表单提交的密码参数名(password)。
    rememberMeParam:表单提交的记住我参数名(rememberMe)。
    loginUrl:登录页面地址(/login.jsp)。
    successUrl:登录成功后的默认重定向地址。
    failureKeyAttribute:登录失败后错误信息存储Key(shiroLoginFailure)。

  • authcBasic(BasicHttpAuthenticationFilter)

    Basic HTTP身份验证拦截器,主要属性:
    applicationName:弹出登录框显示的信息(application)。

  • logout(LogoutFilter)

    退出拦截器,主要属性:
    redirectUrl:退出成功后重定向的地址(/)。
    示例:“/logout=logout”

  • user(UserFilter)

    用户拦截器,用户已经身份验证/记住我登录的都可。
    示例:“/**=user”

  • anon(AnnonymousFilter)

    匿名拦截器,即不需要登录即可访问,一般用于静态资源过滤或者需要在登录之前进行的请求。
    示例:“/static/**=anon”

与授权相关的拦截器

  • roles(RolesAuthorizationFilter)

    角色授权拦截器,验证用户是否拥有所有角色。主要属性:
    loginUrl:登录页面地址(/login.jsp)。
    unauthorizedUrl:未授权后重定向的地址。
    示例:“/admin/**=roles[admin]”

  • perms(PermissionsAuthorizationFilter)

    权限授权拦截器,验证用户是否拥有所有权限,属性和roles一样。
    示例:“/user/**=perms[“user:create”]”

  • port(PortFilter)

    端口拦截器,主要属性:
    port(80):可以通过的端口。
    示例:“/test=port[80]”,如果用户访问该页面是非80端口,将自动将端口改为80并重定向到该80端口,其他路径/参数等都一样。

  • rest(HttpMethodPermissionFilter)

    rest风格拦截器,自动根据请求方法构建权限字符串(GET=read,POST=create,PUT=update,DELETE=delete,HEAD=read,TRACE=read,OPTIONS=read,MKCOL=create)构建权限字符串。
    示例:“/users=rest[user]”,会自动拼出“user:read,user:create,user:update,user:delete”权限字符串进行权限匹配(所有都得匹配,isPermittedAll)。

  • ssl(SslFilter)

    SSL拦截器,只有请求协议是https才能通过,否则自动跳转到https端口(443),其他和port拦截器一样。

其他拦截器

  • noSessionCreation(NoSessionCreationFilter)

    不创建会话拦截器,调用subject.getSession(false)不会有问题,但是如果subject.getSession(true)将抛出异常。

本文原创,才疏学浅,如有纰漏,欢迎指正。如果本文对您有所帮助,欢迎点赞,并期待您的反馈交流,共同成长。
原文地址: https://www.emanjusaka.top/2023/10/filter-shiro-authentication-error-json
微信公众号:emanjusaka的编程栈文章来源地址https://www.toymoban.com/news/detail-711325.html

到了这里,关于自定义过滤器配置 Shiro 认证失败返回 json 数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Gateway自定义过滤器——全局过滤器

    首先,我们要知道全局过滤器其实是特殊路由过滤器(特殊的GatewayFilter),会有条件地作用于所有路由。 为什么要自定义全局过滤器?就好比是看大门的保安大叔,平时主要是做好进出大门外来人员登记即可,但是因为新冠疫情,现在还需要给外来人员测量体温等等。而已有的

    2024年02月16日
    浏览(44)
  • Mongodb过滤器filter选择要返回的数组子集

    Mongodb使用过滤器 $filter 根据指定条件选择要返回的数组子集。返回仅包含与条件匹配的元素的数组。返回的元素按原始顺序排列。 也就是说,这个是选择你要的文档,而不是排除。 如果该数组没有符合条件 ,则为 空 [] $filter: 选择数组的子集以返回仅包含与过滤条件匹配的

    2024年02月16日
    浏览(55)
  • JAVA开发(通过网关gateway过滤器进行返回结果加密)

    在对C的网站或者APP后端接口中,参数的传输往往需要加密传输。这时我们 可以通过springcloud的网关过滤器进行统一的控制。 网关过滤器的执行顺序: 请求进入网关会碰到三类过滤器:当前路由过滤器、DefaultFilter、GlobalFilter。 请求路由后,会将当前路由过滤器和DefaultFilter、

    2023年04月17日
    浏览(52)
  • 在Spring boot中 使用JWT和过滤器实现登录认证

    在navicat中运行如下sql,准备一张user表 导入pom.xml坐标 在工utils包下创建一个用于生成和解析JWT 令牌的工具类 在pojo包下创建user类 在mapper包下添加 UserMapper接口 在service包下添加 UserService类 在utils包下添加统一响应结果封装类 在controller包下添加LoginController类 这样登录获取toke

    2024年02月06日
    浏览(41)
  • SpringCloudGateway--过滤器(自定义filter)

    目录 一、概览  二、全局过滤器GlobalFilter 三、通过GatewayFilter实现 四、继承AbstractGatewayFilterFactory        当使用Spring Cloud Gateway构建API网关时,可以利用Spring Cloud Gateway提供的内置过滤器(filter)来实现对请求的处理和响应的处理。过滤器可以在请求被路由之前或之后被执

    2024年02月06日
    浏览(40)
  • 5.使用日志+自定义全局异常过滤器

    刚开始写文章,封装Base基类的时候,添加了trycatch异常块,不过当时没有去记录日志,直接return了。有小伙伴劝我不要吃了Exception  其实没有啦,项目刚开始,我觉得先做好整体结构比较好。像是盖楼一样。先把楼体建造出来,然后再一步一步的美化完善。 基础的仓储模式已

    2024年02月08日
    浏览(44)
  • Javaweb | 过滤器、配置、过滤器链、优先级

    💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! 概念 过滤器(Filter)是处于客户端与服务器目标资源之间的一道过滤技术 用户的请求和响应都需要经过过滤器 过滤器作用 执行地位在Servlet之前,客户端发送请求是,会先经过Filter,再到达目标Servlet中;响应时,会根

    2023年04月17日
    浏览(50)
  • 如何在Vue中定义和调用过滤器?

    过滤器(Filters)是 vue 为开发者提供的功能,常用于文本的格式化。过滤器可以用在两个地方:插值表达式和 v-bind 属性绑定。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道符”进行调用,示例代码如下: 在创建 vue 实例期间,可以在 filters 节点中定义过滤器,示例代码

    2024年02月09日
    浏览(38)
  • 【Spring Security系列】Spring Security 过滤器详解与基于JDBC的认证实现

    上文说到,Spring Security它是一个强大的和高度可定制的身份验证和访问控制框架。它提供了一套丰富的功能,用于保护基于Spring的应用程序。 上文又说到,在Spring Security中,过滤器(Filter)是一个重要的组件,用于处理身份验证、授权和其他安全相关的任务。 Spring Security 的

    2024年04月22日
    浏览(39)
  • SpringBoot自定义过滤器获取HttpServletRequest和HttpServletResponse的参数

    公司的老系统改造:由于接口日志不全,接口太多,也无法每个接口都加上日志,所以要在网关层统一记录一下日志,并存到数据库中,(以后计划要存储到ES中) 过滤器是基于Servlet规范的组件,作用于整个请求和响应过程,无法直接访问Spring MVC的上下文。过滤器先于拦截

    2024年01月25日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包