【百度搜不到】Spring-Security+Swagger根据指定的用户角色生成不同的API文档

前言

Swagger用来制作API文档十分方便,但是在项目分角色进行API鉴权时,如果事先没有对整个项目的API层级有很好的定义的时候(代码的分包比较混乱,一个controller中包含多个角色调用的接口),会显得整个API文档非常的臃肿,看起来很不方便。
这个问题,就被小编我遇到了。并且在网上浏览时,发现这方面的资料及其少,甚至说没有。。。万不得已,只能去撸一撸swagger的源码,并且源码也搞得我云里雾里的,但还是被我给找到了解决的方法,这里跟大家分享一下。

分析

重头分析下Swagger的配置类

这里着重看下,该配置类向Spring容器里注入Docket对象的配置,Docket其实就是配置API文档生成的参数。
在这里插入图片描述
说明:红框圈起来的就是生成API文档时,配置的请求处理选择器路径选择器,这里用的是默认的Swagger为我们提供的选择器。
RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class):意思就是被ApiOperation注解标注的方法会被添加进来。
PathSelectors.any():意思就是不进行路径过滤,你选出来啥就是啥。

看到这里的时候,突然有了个想法,如果能自己写一个满足需求的选择器,不就解决了吗

接下来看下RequestHandlerSelectors是个啥

这里主要看RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)这个方法返回了一个什么东西?跟到源码里,发现其实很简单。
在这里插入图片描述
就这么一行代码,就判断了一个RequestHandler类型的入参是否被指定的注解标注。

再看下RequestHandler是个啥

点进源码查看时,发现里面有个参数很有意思HandlerMethod
在这里插入图片描述
看到这里,就想着,既然这是选择方法的,会不会就是将扫描出来的方法,封装了一下呢?

最后看下HandlerMethod是个啥

于是就再点进去看了下HandlerMethod的源码,发现一个Method对象的成员变量,截图如下:
在这里插入图片描述

看到这里还是还是有点不确定,于是,将项目用debug模式运行起来,在RequestHandlerSelectors里面打了个断点,想着来验证一下。
连续断点几次之后,发现这些method好眼熟啊,不就是我定义的接口吗?
在这里插入图片描述

分析结果

这个Method就是扫描出来的我们定义的方法对象,那我们拿到这个对象之后,不是想怎么判断就怎么判断吗?感觉要飞起来了。。。
Swagger给的这个默认的选择器里面,只是做了注解判断而已,我们完全可以进行自己的判断啊!!!

实现自定义的RequestHandler选择器

package com.zyu.boot.demo.swagger.selector;

import com.google.common.base.Predicate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.method.HandlerMethod;
import springfox.documentation.RequestHandler;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * 自定义的RequestHandler选择器
 */
public class CustomRequestHandlerSelectors {
    /**
     * 通过指定的方法注解和给定的角色身份选择,身份为空时,默认只采用注解
     * @param annotation
     * @param role
     * @return
     */
    public static Predicate<RequestHandler> withMethodAnnotationAndRole(final Class<? extends Annotation> annotation,String role) {
        return new Predicate<RequestHandler>() {
            public boolean apply(RequestHandler input) {
                if(null == role || "".equals(role.trim()))
                    return input.isAnnotatedWith(annotation);
                //拿到被封装的handlerMethod对象
                HandlerMethod handlerMethod = input.getHandlerMethod();
                //获取真实的method对象
                Method method = handlerMethod.getMethod();
                //TODO:
                // 1 判断方法上有没有PreAuthorize注解,如果有就使用该注解判断角色符合不
                // 2 方法上没有注解,判断类上有没有注解,如果有就是用该注解判断角色符合不
                // 3 都没有注解,返回false,不选择方法
                PreAuthorize authInMethod = method.getAnnotation(PreAuthorize.class);
                if(null != authInMethod){
                    String value = authInMethod.value();//value肯定有值,但可能是空字符串 ""
                    return value.toUpperCase().contains(role.trim().toUpperCase());
                }
                PreAuthorize authInClass = method.getDeclaringClass().getAnnotation(PreAuthorize.class);
                if(null != authInClass){
                    String value = authInClass.value();//value肯定有值,但可能是空字符串 ""
                    //这里判断方法,需要根据自己标注的值,进行自定义匹配(我这里权限标注使用的都是 hasRole("角色名"),设计不同,可能不一样)
                    return value.toUpperCase().contains(role.trim().toUpperCase());
                }
                return false;
            }
        };
    }
}

验证一下

在这里插入图片描述
这里配置了自定义的选择器
在这里插入图片描述

多个API文档

可以在Swagger的配置类中,定义多个Docket对象即可,这样看起来就简单很多了。

结束语

学无止境,诸君共勉

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值