Swagger用过的都知道是在线文档神器,配置步骤也十分简单,但是网上和Spring整合没有结合Spring拦截器一起使用的,今天笔者来抛砖引玉,分享下Swagger整合JWT过程中结合Spring拦截器的使用,有什么不对的地方还请大家指正。
1、pom.xml添加swagger2依赖,目前最新版本的是2.9.2:
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.9.2version>
dependency>
2、新增登陆拦截器,JWT网上有很多实现:
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//从header中取出jwt
String token = request.getHeader("X-Auth-Token");
//...此处省略token验证的过程
return true;
}
}
3、 配置拦截器:
因为swagger也需要用到这些排除的白名单URL,所以白名单URL是放在application.properties这个配置文件的:
weshop-wechat.login-interceptor-exclude-path[0]=/
weshop-wechat.login-interceptor-exclude-path[1]=/csrf
weshop-wechat.login-interceptor-exclude-path[2]=/error
weshop-wechat.login-interceptor-exclude-path[3]=/favicon.ico
weshop-wechat.login-interceptor-exclude-path[4]=/swagger-resources/**
weshop-wechat.login-interceptor-exclude-path[5]=/webjars/**
weshop-wechat.login-interceptor-exclude-path[6]=/v2/**
weshop-wechat.login-interceptor-exclude-path[7]=/swagger-ui.html/**
# 前面几条是固定不需要登录拦截,否则访问Swagger就需要登录了
weshop-wechat.login-interceptor-exclude-path[8]=/wechat/brand/**
weshop-wechat.login-interceptor-exclude-path[9]=/wechat/catalog/**
weshop-wechat.login-interceptor-exclude-path[10]=/wechat/goods/**
weshop-wechat.login-interceptor-exclude-path[11]=/wechat/home/**
weshop-wechat.login-interceptor-exclude-path[12]=/wechat/search/**
weshop-wechat.login-interceptor-exclude-path[13]=/wechat/topic/**
weshop-wechat.login-interceptor-exclude-path[14]=/wechat/auth/login
weshop-wechat.login-interceptor-exclude-path[15]=/wechat/dev/{userId}/token
配置文件类,方便获取白名单的URL数组集合
@ConfigurationProperties(prefix = "weshop-wechat")
public class WeshopWechatProperties {
private List<String> loginInterceptorExcludePath;
public List<String> getLoginInterceptorExcludePath() {
return loginInterceptorExcludePath;
}
public void setLoginInterceptorExcludePath(List<String> loginInterceptorExcludePath) {
this.loginInterceptorExcludePath = loginInterceptorExcludePath;
}
}
拦截器配置的config类
@Configuration
@EnableConfigurationProperties(WeshopWechatProperties.class)
public class WebConfig implements WebMvcConfigurer {
//配置文件类
private final WeshopWechatProperties weshopWechatProperties;
//获取配置的构造方法
public WechatWebConfig(WeshopWechatProperties weshopWechatProperties) {
this.weshopWechatProperties = weshopWechatProperties;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")//拦截所有的路径
.excludePathPatterns(weshopWechatProperties.getLoginInterceptorExcludePath().toArray(new String[]{}));//白名单URL
}
}
4、配置Swagger2,这一步是关键:
@Configuration
@EnableSwagger2 //这个注解一定不能忘记加,否则swagger就不生效,也可以加在启动类上面
@EnableConfigurationProperties(WeshopWechatProperties.class)
public class Swagger2Config {
//这里同样需要用到配置的白名单URL
private WeshopWechatProperties weshopWechatProperties;
public Swagger2Config(WeshopWechatProperties weshopWechatProperties) {
this.weshopWechatProperties = weshopWechatProperties;
}
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("tech.wetech.weshop.wechat.controller"))// 指定api路径
.paths(PathSelectors.any())
.build()
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("微信小程序端接口文档")
.description("WESHOP | 又一个小程序商城应用")
.termsOfServiceUrl("https://github.com/cjbi")
.version("1.0")
.build();
}
private List<ApiKey> securitySchemes() {
//参数1:字段的名字,参数2:字段的键,参数3:参数位置
return Arrays.asList(new ApiKey("Auth-Token", "Auth-Token", "header"));
}
//认证的上下文,这里面需要指定哪些接口需要认证
private List<SecurityContext> securityContexts() {
SecurityContextBuilder builder = SecurityContext.builder().securityReferences(securityReferences());
//指定需要认证的path,大写的注意,这里就用到了配置文件里面的URL,需要自己实现path选择的逻辑
builder.forPaths(forExcludeAntPaths(weshopWechatProperties.getLoginInterceptorExcludePath()));
return Arrays.asList(builder.build());
}
/**
* 匹配登陆拦截器过滤地址
* @param antPatterns - ant Patterns
* @return predicate that matches a particular ant pattern
*/
private Predicate<String> forExcludeAntPaths(final List<String> antPatterns) {
return (input) -> {
//使用spring的ant路径配置
AntPathMatcher matcher = new AntPathMatcher();
//如果不是白名单的URL,就需要认证
return !antPatterns.stream().anyMatch(antPattern -> matcher.match(antPattern, input));
};
}
//这个方法是验证的作用域,不能漏了
private List<SecurityReference> securityReferences() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
return Arrays.asList(
new SecurityReference("Access-Token", new AuthorizationScope[]{authorizationScope}));
}
}
5、代码部分都完成了,来看看最终效果:
这个是登陆窗口,右上角Anthorize按钮可以设置全局Token
需要登陆的接口右边有个小锁,可以设置单个接口的token,没有小锁的就是不需要登陆的白名单接口,是从配置文件读取的
至此,swagger针对Spring拦截器的认证就完成了,欢迎评论给我留言。