文章详情

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

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Security怎么实现接口放通

2023-06-30 15:51

关注

本文小编为大家详细介绍“Spring Security怎么实现接口放通”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring Security怎么实现接口放通”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

1.SpringBoot版本

本文基于的Spring Boot的版本是2.6.7

2.实现思路

新建一个AnonymousAccess注解,该注解是应用于Controller方法上的

新建一个存放所有请求方式的枚举类

通过判断Controller方法上是否存在该注解

SecurityConfig上进行策略的配置

3.实现过程

3.1新建注解

@Inherited@Documented@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface AnonymousAccess {    }

3.2新建请求枚举类

该类是存放所有的请求类型的,代码如下:

@Getter@AllArgsConstructorpublic enum RequestMethodEnum {        GET("GET"),        POST("POST"),        PUT("PUT"),        PATCH("PATCH"),        DELETE("DELETE"),        ALL("All");        private final String type;    public static RequestMethodEnum find(String type) {        for (RequestMethodEnum value : RequestMethodEnum.values()) {            if (value.getType().equals(type)) {                return value;            }        }        return ALL;    }}

3.3判断Controller方法上是否存在该注解

SecurityConfig类中定义一个私有方法getAnonymousUrl,该方法主要作用是判断controller那些方法加上了AnonymousAccess的注解

    private Map<String, Set<String>> getAnonymousUrl(Map<RequestMappingInfo, HandlerMethod> handlerMethodMap) {        Map<String, Set<String>> anonymousUrls = new HashMap<>(8);        Set<String> get = new HashSet<>();        Set<String> post = new HashSet<>();        Set<String> put = new HashSet<>();        Set<String> patch = new HashSet<>();        Set<String> delete = new HashSet<>();        Set<String> all = new HashSet<>();        for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {            HandlerMethod handlerMethod = infoEntry.getValue();            AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);            if (null != anonymousAccess) {                List<RequestMethod> requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods());                RequestMethodEnum request = RequestMethodEnum.find(requestMethods.size() == 0 ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name());                switch (Objects.requireNonNull(request)) {                    case GET:                        get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());                        break;                    case POST:                        post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());                        break;                    case PUT:                        put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());                        break;                    case PATCH:                        patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());                        break;                    case DELETE:                        delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());                        break;                    default:                        all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());                        break;                }            }        }        anonymousUrls.put(RequestMethodEnum.GET.getType(), get);        anonymousUrls.put(RequestMethodEnum.POST.getType(), post);        anonymousUrls.put(RequestMethodEnum.PUT.getType(), put);        anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch);        anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete);        anonymousUrls.put(RequestMethodEnum.ALL.getType(), all);        return anonymousUrls;    }

3.4在SecurityConfig上进行策略的配置

通过一个SpringUtil工具类获取到requestMappingHandlerMappingBean,然后通过getAnonymousUrl方法把标注AnonymousAccess接口找出来。最后,通过antMatchers细腻化到每个 Request 类型。

    @Override    protected void configure(HttpSecurity httpSecurity) throws Exception {        // 搜寻匿名标记 url: @AnonymousAccess        RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) SpringUtil.getBean("requestMappingHandlerMapping");        Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();        // 获取匿名标记        Map<String, Set<String>> anonymousUrls = getAnonymousUrl(handlerMethodMap);        httpSecurity                //禁用CSRF                .csrf().disable()                .authorizeRequests()                // 自定义匿名访问所有url放行:细腻化到每个 Request 类型                // GET                .antMatchers(HttpMethod.GET,anonymousUrls.get(RequestMethodEnum.GET.getType()).toArray(new String[0])).permitAll()                // POST                .antMatchers(HttpMethod.POST,anonymousUrls.get(RequestMethodEnum.POST.getType()).toArray(new String[0])).permitAll()                // PUT                .antMatchers(HttpMethod.PUT,anonymousUrls.get(RequestMethodEnum.PUT.getType()).toArray(new String[0])).permitAll()                // PATCH                .antMatchers(HttpMethod.PATCH,anonymousUrls.get(RequestMethodEnum.PATCH.getType()).toArray(new String[0])).permitAll()                // DELETE                .antMatchers(HttpMethod.DELETE,anonymousUrls.get(RequestMethodEnum.DELETE.getType()).toArray(new String[0])).permitAll()                // 所有类型的接口都放行                .antMatchers(anonymousUrls.get(RequestMethodEnum.ALL.getType()).toArray(new String[0])).permitAll()                // 所有请求都需要认证                .anyRequest().authenticated();            }

3.5在Controller方法上应用

在Controller上把需要的放通的接口上加上注解,即可不需要认证就可以访问了,是不是很方便呢。例如,验证码不需要认证访问的,代码如下:

    @ApiOperation(value = "获取验证码", notes = "获取验证码")    @AnonymousAccess    @GetMapping("/code")    public Object getCode(){        Captcha captcha = loginProperties.getCaptcha();        String uuid = "code-key-"+IdUtil.simpleUUID();        //当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型        String captchaValue = captcha.text();        if(captcha.getCharType()-1 == LoginCodeEnum.ARITHMETIC.ordinal() && captchaValue.contains(".")){            captchaValue = captchaValue.split("\\.")[0];        }        // 保存        redisUtils.set(uuid,captchaValue,loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);        // 验证码信息        Map<String,Object> imgResult = new HashMap<String,Object>(2){{            put("img",captcha.toBase64());            put("uuid",uuid);        }};        return imgResult;    }

3.6效果展示

Spring Security怎么实现接口放通

读到这里,这篇“Spring Security怎么实现接口放通”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

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

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

软考中级精品资料免费领

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

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

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

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

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

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

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