shiro通过注解方式自定义控制接口无需认证访问的解决过程

2023-11-16

1. 需求背景

  用过Shiro的小伙伴都知道,shiro提供两种权限控制方式,通过过滤器注解。我们项目是springboot + vue前后分离项目,后台对于权限控制一直使用的是过滤器的方式,并且还有自定义的过滤器。大概如下:

@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
	ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
	shiroFilter.setSecurityManager(securityManager);
	//过滤规则设置
	Map<String, Filter> filters = new HashMap<>();
	filters.put("shiro", new ShiroAuthenticatingFilter());
	filters.put("user", new UserAuthcFilter());
	shiroFilter.setFilters(filters);
	Map<String, String> filterMap = new LinkedHashMap<>();
	filterMap.put("/captcha.jpg", "anon");
	filterMap.put("/security/login", "anon");
	filterMap.put("/getPublicKey", "anon");
	filterMap.put("/user/logout", "anon");
	filterMap.put("/user/queryByToken", "shiro");
	filterMap.put("/**", "user");
	shiroFilter.setFilterChainDefinitionMap(filterMap);
	retrun shiroFilter;
}

  如上图所示,我们自定义了两种过滤器shirousershiro过滤器用来登录时打通Shiro并存储身份user过滤器用来校验剩余所有接口是否处于登录状态
  当我们需要放开接口时,就像上图一样,配置多个anon。但是由于当前Shiro配置文件也算是项目中的一个主配置文件,总是让开发不断修改这个文件。
  对于一个严谨的猴子来说,这种事儿不能够发生。应该严格遵循开闭原则的设计,对扩展开放、对修改关闭。应该将所有需要修改的拿到外边,当前配置文件纳入到系统jar包里,只允许引用。我想要的效果如下:
在这里插入图片描述

2. 解决思路

  因为从我们变化的地方来看,其实经常变化的就是增删那些不需要登录即可访问的接口
  既然Shiro自己提供注解,那可以通过过滤器+注解的方式来解决,上图的配置就改成下边这样:

@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
	ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
	shiroFilter.setSecurityManager(securityManager);
	//过滤规则设置
	Map<String, Filter> filters = new HashMap<>();
	filters.put("shiro", new ShiroAuthenticatingFilter());
	filters.put("user", new UserAuthcFilter());
	shiroFilter.setFilters(filters);
	Map<String, String> filterMap = new LinkedHashMap<>();
	/******只是将所有的anon提取出来,不再修改这里*******/
	filterMap.put("/user/queryByToken", "shiro");
	filterMap.put("/**", "user");
	shiroFilter.setFilterChainDefinitionMap(filterMap);
	retrun shiroFilter;
}

  然后再利用Shiro自带的注解@RequiresGuest,想哪个接口放开,我就把这个注解加到那个Controller对应的放开接口上即可,如下:

  /**
     * 获取学生详细信息
     */
    @RequiresGuest
    @PostMapping(value = "/get")
    public Result getInfo(@RequestBody @Validated(SelectOne.class) DemoGradeStudentModel model) {
        return Result.data(demoGradeStudentService.getById(model.getId()));
    }

  因为我们需要放开的接口数量远远少于需要拦截的接口,因此通过控制配置放开的注解来实现这样的功能,是最好的方式。
  思路是不是很简单,对,我也是三下五除二就这么配置完了,然而事实打脸了,并不管用
  经过网上搜索,全都是需要添加以下注解:

@Bean({"lifecycleBeanPostProcessor"})
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

  然而并不管用

3. 原因追踪

3.1 排查拦截过滤器逻辑

  通过debug来看,因为我的所有剩余拦截的方式,都基于自定义过滤器user,大家可能有的是自定义,有的是基于Shiro自带的authc过滤器,具体需要大家各自找到对应的过滤器,因此我找到了我自己的那个过滤器里边。如下图:
在这里插入图片描述
   通过Debug模式下,发现如果在未登录情况下访问接口,首先进入上图的isAccessAllowed方法,因为我的请求既不是登录页,也没有登录身份,那妥妥的在这个方法里返回false。返回false的结果就是会接着进入下边的方法onAccessDenied,该方法里封装未登录的返回结果,之后也并没有进入到Shiro自带的@RequiresGuest注解的拦截,就返回提示了。
   这是为什么呢?为什么不进入@RequiresGuest对应的拦截。
   从一方面来看,因为注解的这种AOP方式,全都是拦截器,而拦截器发生在过滤器之后,因为在上边的过滤器里已经处理为错误,因此也没法进入拦截器,看起来不生效的原因显而易见。我也试过把我的拦截过滤器改成自带的authc过滤器,仍然不行。

3.2 排查Shiro自带的注解

   经过我的排查,我发现Shiro的注解并不满足我的情况(基于我们自己的过滤器添加注解)。有以下几个原因:

  1. 配置繁琐。 Shiro里如果要想把所有接口都拦截,都需要往每个Controller里加@RequiresAuthentication注解,如果没有登录,当前类下的所有方法都不能访问。我也不能写一个Controller就加一个这个注解,多有失我的身份?当然肯定也可以自定义一个拦截器来控制,但是一定要防备像我上边的情况,过滤器给直接拦住了,注解都没有生效的情况。
  2. 不可交叉配置。比如我只想放开某个类里的固定一个接口,如果Controller上配置@RequiresAuthentication注解,在要放开的接口上配置@RequiresGuest注解,貌似是不生效的,即不是根据方法最优的方式来做的(这块我看过部分源码,其实看源码,感觉是满足的,但是实际情况下,我的确是出现不生效的情况,这里也不把准。)

  注意:以前并没有用过这些注解,可能理解片面了,具体情况要分析下自己项目的过滤规则是怎么走的。

4. 最终解决思路优化

   最终,我认为@RequiresGuest注解很鸡肋有限。我感觉我需要解决的只是随便一个自定义的注解。我只要保证能够在我的user过滤器中(3.1图)的isAccessAllowed方法中,通过请求的Request对象拿到请求uri,根据uri找到对应的接口方法,然后再看这个方法上对应的有没有我这个自定义的放开权限的注解,如果有,那就不需要验证,直接放行不就可以了吗?
   等等,这个逻辑似曾相识:

拿到请求uri
request
找到具体的方法
查看方法上的注解

   这不就是我们正常访问一个后台接口,需要走的逻辑吗?比如我访问下图的/student/get这样的后台接口。spring如何通过请求request找到的具体的方法?

  /**
     * 获取学生详细信息
     */
    @RequiresGuest
    @PostMapping(value = "/get")
    public Result getInfo(@RequestBody @Validated(SelectOne.class) DemoGradeStudentModel model) {
        return Result.data(demoGradeStudentService.getById(model.getId()));
    }

   因此我就开始搜spring怎么做到的,最后,找到了RequestMappingHandlerMapping 这个家伙,在spring启动后,容器里会把所有的接口地址与方法的关系维护在这个RequestMappingHandlerMapping 类中,它有一个方法getHandler(httpServletRequest),是可以通过request找到对应的方法,在我使用的时候,我发现这个家伙真是好人,它肚子里连方法带的注解都有,不需要我再做处理,如下图所示:
在这里插入图片描述
   通过上图来看,那就很明白了,只要我比较一下declaredAnnotations集合中是否存在我自定义的@GuestAccess注解,如果存在,那就放行,如果不存在,就正常的判断就可以了。

5. 处理步骤

   根据上边的方式,开始进行修改

5.1 自定义注解

   定义了一个简单的注解,目前我只允许加到方法上,并不支持加到类上。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 自定义shiro注解,用于放开认证的接口
 * 通过对controller的接口方法添加该注解,实现不需要登录既可以访问。
 * @author lingsf
 * @date 2021/1/25
 */
@Target(value ={ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface GuestAccess {
}

5.2 修改验证权限的过滤器

   找到对应的UserAuthcFilter过滤器(3.1所示图),如下图代码块:

protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        if(this.isLoginRequest(request, response)) {
            return true;
        } else {
            Subject subject = this.getSubject(request, response);
            return subject.getPrincipal() != null;
        }
    }

    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
    //省略
       }

   主要修改isAccessAllowed方法:
   下边仅仅支持将注解放到方法上,如果想支持类,可看本文最后的扩展部分。

protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
/*********************添加如下内容***********************/
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        WebApplicationContext ctx = RequestContextUtils.findWebApplicationContext(httpServletRequest);
        RequestMappingHandlerMapping mapping = ctx.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
        HandlerExecutionChain handler = null;
        try {
            handler = mapping.getHandler(httpServletRequest);
            Annotation[] declaredAnnotations = ((HandlerMethod) handler.getHandler()).
                    getMethod().getDeclaredAnnotations();
            for(Annotation annotation:declaredAnnotations){
				/**
				*如果含有@GuestAccess注解,则认为是不需要验证是否登录,
				*直接放行即可
				**/
                if(GuestAccess.class.equals(annotation.annotationType())){
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
/*********************添加如上内容***********************/
        return this.getSubject(request, response).getPrincipal() != null;
    }

    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
    //省略
       }

   最后,再将shiroFilter对应的anon配置全部删除,如下图:

@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
	ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
	shiroFilter.setSecurityManager(securityManager);
	//过滤规则设置
	Map<String, Filter> filters = new HashMap<>();
	filters.put("shiro", new ShiroAuthenticatingFilter());
	filters.put("user", new UserAuthcFilter());
	shiroFilter.setFilters(filters);
	Map<String, String> filterMap = new LinkedHashMap<>();
	/******只是将所有的anon提取出来,不再修改这里*******/
	filterMap.put("/user/queryByToken", "shiro");
	filterMap.put("/**", "user");
	shiroFilter.setFilterChainDefinitionMap(filterMap);
	retrun shiroFilter;
}

5.3 放行的接口上加@GuestAccess注解

   最后,就可以在需要放开的接口上加@GuestAccess
就可以了。

  /**
     * 获取学生详细信息
     */
    @GuestAccess
    @PostMapping(value = "/get")
    public Result getInfo(@RequestBody @Validated(SelectOne.class) DemoGradeStudentModel model) {
        return Result.data(demoGradeStudentService.getById(model.getId()));
    }

6. 扩展及总结

  目前这个自定义注解仅仅在方法上有效,可以扩展为支持整个controller,这样会更加好一些。
  本次的功能实现,对于通过request找到对应的方法有更深的了解,学习到了RequestMappingHandlerMapping的使用方法。

7. 10.27号扩展

  最近这个地方因为业务需要,必须要让整个Controller的所有方法支持游客注解。又找到了更好的方法,有小伙伴问我这块,我就直接将逻辑贴在下边了。
   其实主要是因为我有发现了一个更好的spring方法spring-core包里的。AnnotationUtils.getAnnotation(var1,var2),这个更牛,支持类和方法。
   代码如下,大家参考:

protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
/*********************添加如下内容***********************/
       HttpServletRequest httpRequest = WebUtils.toHttp(request);
        WebUtils.saveRequest(request);
        WebApplicationContext ctx = RequestContextUtils.findWebApplicationContext(httpRequest);
        RequestMappingHandlerMapping mapping = ctx.getBean
                ("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
        HandlerExecutionChain handler = null;
        try {
            handler = mapping.getHandler(httpRequest);
            HandlerMethod handlerClass = (HandlerMethod)handler.getHandler();
            Class<?> nowClass = handlerClass.getBeanType();
            GuestAccess classWithGuestAccess = AnnotationUtils.getAnnotation(nowClass, GuestAccess.class);
            if(classWithGuestAccess != null) {
                return true;
            }
            GuestAccess methodWithGuestAccess = AnnotationUtils.getAnnotation(handlerClass.getMethod(), GuestAccess.class);
            if(methodWithGuestAccess != null) {
                return true;
            }
        } catch (Exception var12) {
            var12.printStackTrace();
            throw new RuntimeException(var12);
        }

    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
    //省略
       }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

shiro通过注解方式自定义控制接口无需认证访问的解决过程 的相关文章

  • SpringMVC+Apache Shiro+JPA(hibernate)案例教学(一)整合配置

    序 关于标题 说是教学 实在愧不敢当 但苦与本人文笔有限 实在找不到更合理 谦逊的词语表达 只能先这样定义了 其实最真实的想法 只是希望这个关键词能让更多的人浏览到这篇文章 也算是对于自己写文章的一个肯定吧 关于内容 再写这系列文章之前 本
  • shiro 动态修改资源权限不需要重启项目或者重新登录用户

    用shiro做权限控制的时候 变更用户或者角色的权限后刷新界面不会重新加载权限 需要重启tomcat或者用户重新登录 特别的不人性化 通过下面的方式可以解决这个问题 但仅仅针对于单机 对集群来说就不太清楚 以后有了更好的方法再去使用 菜鸟级
  • Shiro使用redis作为缓存(解决shiro频繁访问Redis)(十一)

    原文地址 转载请注明出处 https blog csdn net qq 34021712 article details 80791219 王赛超 之前写过一篇博客 使用的一个开源项目 实现了redis作为缓存 缓存用户的权限 和 sess
  • ShiroFilter设计原理与实现

    Shiro提供了与Web集成的支持 其通过一个ShiroFilter入口来拦截需要安全控制的URL 然后进行相应的控制 ShiroFilter类似于如Strut2 SpringMVC这种web框架的前端控制器 其是安全控制的入口点 其负责读
  • Shiro学习(5)-会话管理

    1 会话管理 相关的 API 会话监听器 配置案例 2 缓存 3 记住我
  • Shiro实战学习笔记(2)-自定义Realm

    1 自定义realm package org tzb realm import org apache shiro authc AuthenticationException import org apache shiro authc Aut
  • SpringMVC+Shiro整合配置文件详解

    在项目中xml文件的配置是必不可少的 特别是SpringMVC框架 但是几乎所有项目的配置都是大同小异 很多人都是直接复制黏贴了事 不少人对其具体含义及用途都不甚全知 本片文章将正对项目中常用的框架SpringMVC Shiro进行整合 并
  • Shiro简单配置Springboot版(1)

    1 权限的管理 1 1 什么是权限管理 基本上涉及到用户参与的系统都要进行权限管理 权限管理属于系统安全的范畴 权限管理实现对用户访问系统的控制 按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源 权限管理包括用户身份认证
  • Shiro学习小记--身份验证得到principals

    项目使用shiro进行权限管理 Shiro国内目前资料极少 学习时完全就是根据张开涛的 跟我学Shiro 自己去摸索的 慢慢的开始入门 Shiro中有一个概念是principals 解释如下 principals 身份 即主体的标识属性 可
  • shrio验证cookie有效性

    shrio验证cookie有效性 概述 shrio中提供cookie管理的功能 当用户选择了rememberMe 则下次不需要再登录 而是直接通过本地记录的cookie进行验证 然后就可以访问权限为user的页面 问题 shiro提供清除用
  • 7、Shiro+SpringMVC+oracle+maven整合

    本章节主要介绍Shiro SpringMVC oracle maven整合 并实现shiro的身份验证和授权 建表并插入数据 1 用户表 CREATETABLEusers Table user id number 10 primarykey
  • SpringBoot 整合 Shiro 常见配置

    目录 一 Shiro 基础解释 过滤器 AOP 实现安全认证权限管理逻辑 了解 Shiro 的组织架构 二 SpringBoot 整合 Shiro 1 在项目中使用 Shiro 需要配置的地方 2 代码示例 引入依赖 请求接口 自定义 Re
  • Java面试题--shiro

    Shiro可以做哪些工作 Shiro可以帮助我们完成 认证 授权 加密 会话管理 与Web集成 缓存等 shiro有哪些组件 Authentication 身份认证 登录 验证用户是不是拥有相应的身份 Authorization 授权 即权
  • springboot使用shiro的@Requiresroles注解不起作用(解决方法)

    看shiro的视频发现 Requiresroles不生效 解决方法 spring容器中 Bean public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator DefaultAd
  • Shiro中Session和Cache

    Session是一种状态保持机制 参考文章Session是什么可知Session和Web服务也没有必然关系 Shiro本身的Security Manager也可以脱离Servlet自己管理Session 根据Security Manager
  • shiro使用自定义realm实现数据认证

    自定义realm实现数据认证 在开发中 有时会与一些nosql或者其他地方保存的数据进行认证 这时候 shiro定义的那些realm类可能不能满足实际的功能需求 这时候我们可以通过自定义一个realm来沟通这些数据 实现认证和权限控制 首先
  • 关于shiro doGetAuthorizationInfo授权方法和doGetAuthenticationInfo登陆认证方法的执行时机

    1 默认情况下不关闭shiro session 登陆时生成JESSIONID 执行doGetAuthorizationInfo的时机 1 subject hasRole admin 或 subject isPermitted admin 自
  • Shiro权限管理框架

    Shiro 一 Shiro权限 什么是权限控制 忽略特别细的概念 比如权限能细分很多种 功能权限 数据权限 管理权限等 理解两个概念 用户和资源 让指定的用户 只能操作指定的资源 CRUD 初学javaweb时怎么做 Filter接口中有一
  • 在微服务项目中,Spring Security 比 Shiro 强在哪?

    Spring Security 和Shiro的区别
  • Apache Shiro EhCache初始化异常:同一VM中已存在另一个未命名的CacheManager

    我正在尝试将 EhCache 配置为处理启用 Apache Shiro 的 Web 服务中的授权缓存 目前我收到以下异常 org apache shiro cache CacheException net sf ehcache CacheE

随机推荐

  • 微信小游戏 can't find variable: window

    最近测试微信小游戏的时候 需要加入一些SDK代码 在加入这些文件到项目并require相应的库的时候 小游戏开发者工具一直报错 can t find variable window 查找了相关资料 https developers weix
  • 逐点插入法实现 Delaunary三角网 ( 附 C++ 代码)

    逐点插入法作为一种经典的凸闭包收缩算法 其思想是 首先找到包含数据区域的最小凸包边形 并从该多边形开始从外到内形成Delaunary三角网 因此其每次插入一个新的点就会删除相应的三角形来构建性的三角网 这个过程中常常伴随着大量的查询计算过程
  • flutter 从A到B,然后在从B返回A页面,A页面刷新数据

    flutter 从A到B 然后在从B返回A页面 A页面刷新数据实现代码如下 Navigator push context MaterialPageRoute builder context gt NoticePage then value
  • 解决java.lang.IllegalArgumentException: Could not resolve placeholder xx.xx.addr 的问题,思路:一定是配置文件问题

    今天启动SpringBoot遇到一个问题 提示 java lang IllegalArgumentException Could not resolve placeholder xx xx addr in value xx xx addr
  • pytorch源码解读——RNN/LSTM篇

    文章的字母中 b batch size t time step n num feature h hidden size 假设输入数据维度input b t n 所设计的LSTM模型如下 class MYLSTM nn Module def
  • OkHttpUtils 下载上传文件

    目录 一 使用时需要先添加依赖 build gradle文件中 二 使用注意事项 三 OkHttpUtils 目前支持 3 1 统一的文件下载管理 DownloadManager 3 2 统一的文件上传管理 UploadManager 四
  • 硬链接与软连接:

    磁盘文件简单的一个框架图 磁盘里的文件系统如何管理 将磁盘划分成几个区域 前面是磁盘信息 第一个区域 放的是超级块 第二个区域 是inode 在磁盘上每创建一个文件 就会对应一个inode的结构体 第三个区域 目录项 目录项分为两项 第一项
  • linux下oracle启动过程

    在linux下启动oracle 和在windows是有差别的 对于一般在windows下操作习惯人有很多不适应 所以我特别写这样文章 以方便新手进行操作 下面就一步一步讲解启动过程 1 通过终端连接到linux服务器 当然这样的软件很多例如
  • 腾讯T2亲自教你!2021年Android工作或许更难找,送大厂面经一份!

    近日一好友去阿里面试 面试失败了 分享了一个他最不擅长的算法面试题 题目是这样的 题目 给定一个二叉搜索树 BST 找到树中第 K 小的节点 出题人 阿里巴巴出题专家 文景 阿里云 CDN 资深技术专家 参考答案 考察点 基础数据结构的理解
  • tronweb 波场导入助记词生成地址

    创建助记词 let tronWeb require tronweb let mne tronWeb createRandom 导入助记词 let tronWalletImport tronWeb fromMnemonic m m 44 19
  • echarts laben 饼图指示线条+文字颜色继承

    注意 label并不支持HTML片段 版本5 30 label show true alignTo edge position outside formatter name b n time c 小时 formatter b b n cst
  • Vue3挂载全局方法及组件中如何使用

    文章目录 前言 一 在mian ts mian js 中配置全局变量 1 如何封装 二 如何调用 1 template中调用 2 在script标签中如何拿到 前言 在Vue3项目中 需要频繁使用某一个方法 配置到全局感觉会方便很多 例如
  • Nodejs中electron IpcMain & IpcRenderer通信

    1 事情起因 原因是本人在使用nedb数据库进行数据插入的时候 发现莫名其妙多出了很多很多的数据 很容易想到 那么就是插入语句被调用了N多次 并且每一次插入的数据都是之前已经插入过的数据 比如说第一次插入的是 id 1 name xx 第二
  • MongoDB 聚合

    MongoDB 聚合有什么用 实际项目中 我们经常需要将多个文档甚至是多个集合汇总到一起计算分析 比如求和 取最大值 并返回计算后的结果 这个过程被称为 聚合操作 根据官方文档介绍 我们可以使用聚合操作来 将来自多个文档的值组合在一起 对集
  • 我赌你不懂系列:char占几个字节

    前言 我百度搜索 char占几个字节 得到下面的答案 image png char用于C或C 中定义字符型变量 只占一个字节 取值范围为 128 127 27 27 1 char类型占1字节 就是8位 所能存储的正整数是 0111 1111
  • linux status文件,linux的 functions之status函数详解

    检测一个二进制可运行程序是否运行 使用方法 status p pidfile program status local base pid pid file Test syntax 测试调用该函数时的参数格式 if 0 then echo U
  • Mpvue-echarts发布自定义事件

    引入库 npm install mpvue echarts 直接上源码
  • MyBatis学习-getMapper接口绑定方案及多参数传递

    一 采用接口绑定方案的作用 创建一个接口后 MyBatis框架将mapper xml通过反射机制生成接口的实现类 通过调用接口对象就可以获取mapper xml中编写的sql 方便sql语句的调用 方便多个参数的传递 在未使用接口绑定方案前
  • Layui实现登录注册共用页面

    正文 创建一个Spring Boot项目 勾选Web Thymeleaf即可 pom文件中导入图片验证码的依赖
  • shiro通过注解方式自定义控制接口无需认证访问的解决过程

    1 需求背景 用过Shiro的小伙伴都知道 shiro提供两种权限控制方式 通过过滤器或注解 我们项目是springboot vue前后分离项目 后台对于权限控制一直使用的是过滤器的方式 并且还有自定义的过滤器 大概如下 Bean shir