文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Ruo-Yi 前后端分离如何不登录直接访问以及一种基于配置文件实现的方式

2023-09-07 13:13

关注

Ruo-Yi 前后端分离如何不登录直接访问

问题

​ 我们从若依项目的简介中可以知道,若依前后端分离系统采用了Spring Security作为权限校验框架,那么,如果我们想要不登录就可以访问某些页面应该怎么办?

分析

​ 若依官网的解释:若依官网解释

​ 有关spring security配置的东西若依框架都在SecurityConfig类里面有写。找到configure()方法,一般这个类里面会写。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eQGlma5G-1666317952035)(Ruo-Yi 前后端分离如何不登录直接访问.assets/image-20221021092551886.png)]

这里的意思就是 permitAllUrl.getUrls()集合 里面的路径因为后面设置了permitAll()用户可以任意访问。所以我们要想某些路径不登陆就可以访问,其实只需要我们的不登陆像访问的路径在 permitAllUrl.getUrls()集合里面即可。

# 若依原作者的注释* anyRequest          |   匹配所有请求路径* access              |   SpringEl表达式结果为true时可以访问* anonymous           |   匿名可以访问* denyAll             |   用户不能访问* fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)* hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问* hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问* hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问* hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问* hasRole             |   如果有参数,参数表示角色,则其角色可以访问* permitAll           |   用户可以任意访问* rememberMe          |   允许通过remember-me登录的用户访问* authenticated       |   用户登录后可访问

SecurityConfig 类里面有如下代码:

@Autowiredprivate PermitAllUrlProperties permitAllUrl;

permitAllUrl 是从这里注入进来的,想要知道怎么不登陆就可以访问,就必须分析类PermitAllUrlProperties

PermitAllUrlProperties 类

这个类有@Configuration注解,代表这个类是已启动就被注册到 spring 容器里面。

package com.ruoyi.framework.config.properties;import com.ruoyi.common.annotation.Anonymous;import org.apache.commons.lang3.RegExUtils;import org.springframework.beans.BeansException;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.context.annotation.Configuration;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.Optional;import java.util.regex.Pattern;@Configurationpublic class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware{    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");    private ApplicationContext applicationContext;    private List<String> urls = new ArrayList<>();    public String ASTERISK = "*";    @Override    public void afterPropertiesSet()    {                RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);        // HandlerMethod 类用于封装控制器方法信息,包含类信息、方法Method对象、参数、注解等信息,具体的接口请求是可以根据封装的信息调用具体的方法来执行业务逻辑;        // RequestMappingInfo其实就是将我们熟悉的@RequestMapping注解的信息数据封装到了RequestMappingInfo POJO对象之中,然后和HandlerMethod做映射关系存入缓存之中;        // 可以参考博客:https://blog.csdn.net/yaomingyang/article/details/107026595        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();        map.keySet().forEach(info -> {            HandlerMethod handlerMethod = map.get(info);            // 获取方法上边的注解 替代path variable 为 *            // 从类或方法中查找某个 Anonymous 注解            Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);            Optional.ofNullable(method).ifPresent(anonymous -> info.getPatternsCondition().getPatterns()                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));            // 获取类上边的注解, 替代path variable 为 *            Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);            Optional.ofNullable(controller).ifPresent(anonymous -> info.getPatternsCondition().getPatterns()                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));        });    }    @Override    public void setApplicationContext(ApplicationContext context) throws BeansException    {        this.applicationContext = context;    }    public List<String> getUrls()    {        return urls;    }    public void setUrls(List<String> urls)    {        this.urls = urls;    }}

从上面的代码我们知道,只要我们给类上加 @Anonymous注解,就可以将不登陆就可以访问的路径加入urls集合里面。

@Target({ ElementType.METHOD, ElementType.TYPE })@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Anonymous{}

测试

有了以上的分析,我们接下来测试一波。我们测试缓存监控页面,请求为

http://localhost/dev-api/monitor/cache

不加@Anonymous注解之前:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nOqAddEE-1666317952035)(Ruo-Yi 前后端分离如何不登录直接访问.assets/image-20221021094638260.png)]

测试结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wURyqbFA-1666317952035)(Ruo-Yi 前后端分离如何不登录直接访问.assets/image-20221021094603553.png)]

加了 @Anonymous注解之后:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HeCxHhwF-1666317952036)(Ruo-Yi 前后端分离如何不登录直接访问.assets/image-20221021094742483.png)]

测试结果,访问成功:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GHfwbPa1-1666317952036)(Ruo-Yi 前后端分离如何不登录直接访问.assets/image-20221021094804998.png)]

总结

在若依的系统里面,如果我们想要实现某一个接口不登陆就可以访问,只需要在方法上添加 @Anonymous注解即可。

如果我们想要在我们的项目里面实现不登陆就可以访问,我们可以将若依的PermitAllUrlProperties类和Anonymous类拿过来,然后在SecurityConfigspring security的配置类添加如下代码。

@Autowiredprivate PermitAllUrlProperties permitAllUrl;@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception{    // 注解标记允许匿名访问的url    // 自定义@Anonymous注解添加到方法上可以实现跳过权限验证。    ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();    permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());    // ....     }

拓展:另一种方法基于配置文件

​ 经过上面的分析,我们知道,实现不登陆就可以访问某些接口,若依系统采用的是注解的形式,其实我们还可以将不需要登陆的接口放入配置文件里面。

SecurityConfig类改为

//@Autowired//private PermitAllUrlProperties permitAllUrl;@Resourceprivate IgnoreUrlsConfig ignoreUrlsConfig;@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception{    // 注解标记允许匿名访问的url    // 自定义@Anonymous注解添加到方法上可以实现跳过权限验证。    ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();    // permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());    // 白名单    //不需要保护的资源路径允许访问    for (String url : ignoreUrlsConfig.getUrls()) {        registry.antMatchers(url).permitAll();    }

去掉原有的方式的类的注入,添加IgnoreUrlsConfig

添加类 IgnoreUrlsConfig

@Component@ConfigurationProperties(prefix = "secure.ignore")public class IgnoreUrlsConfig {    private List<String> urls = new ArrayList<>();    public List<String> getUrls() {        return urls;    }    public void setUrls(List<String> urls) {        this.urls = urls;    }}

application.yml添加白名单

secure:  ignore:    urls: #安全路径白名单      - /monitor/cache

测试,还是测试之前的接口

http://localhost/dev-api/monitor/cache

记住,去掉权限的注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HeZUQ55l-1666317952036)(Ruo-Yi 前后端分离如何不登录直接访问.assets/image-20221021100236661.png)]

测试成功:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bx4XtUqK-1666317952037)(Ruo-Yi 前后端分离如何不登录直接访问.assets/image-20221021100248640.png)]

以上的两种方法,我自己还是比较喜欢第二种,想要添加或者删除不需要登陆就可以访问的路径只需要修改配置文件即可,还不会污染业务代码。

来源地址:https://blog.csdn.net/H_Q_Li/article/details/127440502

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯