by emanjusaka from ​ https://www.emanjusaka.top/archives/11 彼岸花开可奈何

本文欢迎分享与聚合,全文转载请留下原文地址。

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/archives/11

微信公众号:emanjusaka的编程栈

自定义过滤器配置 Shiro 认证失败返回 json 数据的更多相关文章

  1. Shiro 认证失败返回JSON

    Shiro框架默认认证失败后会返回到登录页面,在前后端分离项目中,需要返回JSON数据,以便前端或者app端解析处理. 实现方式: 1. 扩展shiro框架的UserFilter类,重写redirec ...

  2. 【转】ASP.NET Core WebAPI JWT Bearer 认证失败返回自定义数据 Json

    应用场景:当前我们给微信小程序提供服务接口,接口中使用了权限认证这一块,当我使用 JWT Bearer 进行接口权限认证的时候,返回的结果不是我们客户端想要的,其它我们想要给客户端返回统一的数据结构, ...

  3. shiro异步请求返回JSON响应

    shiro异步请求返回JSON响应 需求1:当shiro请求资源,但是没有进行认证时,默认是进行重定向,现在需要返回JSON响应.注意异步请求,服务器重定向后,ajax拿到的是浏览器重定向后的到的页面 ...

  4. SpringBoot+SpringSecurity+Thymeleaf认证失败返回错误信息踩坑记录

    Spring boot +Spring Security + Thymeleaf认证失败返回错误信息踩坑记录 步入8102年,现在企业开发追求快速,Springboot以多种优秀特性引领潮流,在众多使 ...

  5. springMvc配置xml使ResponseBody返回Json

    @ResponseBody 在返回的数据不是html标签的页面,而是其他某种格式的数据时(如json.xml等)使用: 不在springMvc中配置json的处理的话,我们通常会在Controller ...

  6. 配置完aop不能返回json

    遇到一个bug,配置了记录controller层的aop,后来发现是因为我aop是写在controller层(在springmvc的容器中)而开启aop配置却写在spring中,所以不起作用,需要在s ...

  7. struts2 的验证框架validation如何返回json数据 以方便ajax交互

    struts2 的验证框架validation简单,好用,但是input只能输出到jsp页面通过struts2的标签<s:fielderror  />才能取出,(EL应该也可以). 如果使 ...

  8. spingmvc 返回json数据日期格式化方法

    第一种: json 用的是这个依赖 <!-- JSON lib 开发包 以及它的依赖包 --> <dependency> <groupId>com.fasterxm ...

  9. Spring MVC 3.0 返回JSON数据的方法

    Spring MVC 3.0 返回JSON数据的方法1. 直接 PrintWriter 输出2. 使用 JSP 视图3. 使用Spring内置的支持// Spring MVC 配置<bean c ...

  10. idea+springmvc+spring+mybatis+maven整合返回json数据webapi

    首先看一张目录结构图: : 创建步骤: 1.创建maven  webapp工程, 创建完后的目录结构为: 2.添加项目依赖(添加jar包) 需要的jar包: spring-webmvc, spring ...

随机推荐

  1. 基于python+django的宠物商店-宠物管理系统设计与实现

    该系统是基于python+django开发的宠物商店-宠物管理系统.是给师妹开发的课程作业.现将源码开放给大家.大家学习过程中,如遇问题可以在github咨询作者. 演示地址 前台地址: http:/ ...

  2. 一文了解 io.LimitedReader类型

    1. 引言 io.LimitedReader 提供了一个有限的读取功能,能够手动设置最多从数据源最多读取的字节数.本文我们将从 io.LimitedReader 的基本定义出发,讲述其基本使用和实现原 ...

  3. Cookie相关基础

    1) 创建Cookie对象, public Cookie(java.lang.String name, java.lang.String value) 参数1:表示cookie名称 参数2:表示coo ...

  4. 【NestJS系列】DI依赖注入与IOC控制反转

    前言 上篇文章我们学习了如何使用nest-cli来快速生成一个NestJS后端项目,当我们打开编辑器查看代码时,会发现整个代码风格有点类似JAVA的spring框架,并且你会发现一些service类在 ...

  5. PREDIV与PLLMUL配置应用笔记

    下图为CH32V305/307和CH32F205/207时钟树框图,在此,以CH32V307VCT6芯片,外置25MHz晶振为例,简述图中PREDIV与PLLMUL的配置方法,最终实现144MHz系统 ...

  6. Git 环境配置(详解版)

    前言 Git下载官网:https://git-scm.com/downloads 本次使用Github为配置前提(Gitee步骤类似) 环境搭建 1.git安装好去GitHub上注册一个账号,注册好后 ...

  7. MAUI Blazor Android 输入框软键盘遮挡问题2.0

    前言 关于MAUI Blazor Android 输入框软键盘遮挡问题,之前的文章已经有了答案,MAUI Blazor Android 输入框软键盘遮挡问题 但是这个方案一直存在一点小的瑕疵 在小窗模 ...

  8. OceanBase 分布式存储管理

    分布式存储管理 分区表管理 定义 把普通的表的数据按照一定的规则划分到不同的区块内,同一区块的数据物理上存储在一起. 每个分区还能按照一定的规则再拆分成多个分区,这种分区表叫做二级分区表. 分区分类 ...

  9. Mysql高级2-SQL性能分析

    一.SQL执行频率 MySQL客户端 连接成功后,通过show [session | global] status 命令可以提供服务器状态信息,通过如下指令,可以查看当前数据库的insert,upda ...

  10. Echarts: 同时显示柱状图和前端

    完整代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...