swagger与oauth的集成使用
1.Swagger定义
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。
个人觉得,swagger的一个最大的优点是能实时同步api与文档。在项目开发过程中,发生过多次:修改代码但是没有更新文档,前端还是按照老旧的文档进行开发,在联调过程中才发现问题的情况(当然依据开闭原则,对接口的修改是不允许的,但是在项目不稳定阶段,这种情况很难避免)。
作用:
- 接口的文档在线自动生成。
- 功能测试。
2.示例
2.1 引入依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>com.joinbright.f1</groupId>
<artifactId>f1-component</artifactId>
<version>3.2.0-SNAPSHOT</version>
</dependency>
第一个是API获取的包,第二是官方给出的一个ui界面。
2.2 SwaggerConfigure
@Configuration
@EnableSwagger2
public class SwaggerConfigure implements Serializable {
// 2.针对授权认证
// security.userOauth.clientId
@Value("${security.userOauth.clientId}")
private String authClientId;
// security.userOauth.clientSecret
@Value("${security.userOauth.clientSecret}")
private String authClientSecret;
@Value("${security.userOauth.type}")
private String type;
// security.userOauth.authorizationUrl
@Value("${security.userOauth.authorizationUrl}")
private String authorizationUrl;
// security.userOauth.tokenUrl
@Value("${security.userOauth.tokenUrl}")
private String tokenUrl;
@Value("${security.userOauth.tokenName}")
private String tokenName;
@Value("${security.userOauth.scope.code}")
private String scopeCode;
@Value("${security.userOauth.scope.desc}")
private String scopeDesc;
@Value("${app.key}")
private String appKey;
@Value("${app.name}")
private String appName;
@Value("${app.desc}")
private String appDesc;
@Value("${app.version}")
private String appVersion;
@Value("${app.termsOfServiceUrl}")
private String termsOfServiceUrl;
@Value("${app.contact.name}")
private String contactName;
/**
* Api分组,可以定义多个组
*/
@Bean
public Docket jackApi() {
return new Docket(DocumentationType.SWAGGER_2).groupName("jack")
.genericModelSubstitutes(DeferredResult.class)
.useDefaultResponseMessages(false)
.forCodeGeneration(true)
.pathMapping("/")
.select()
// .apis(RequestHandlerSelectors.basePackage("net.jack.lt"))
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.securitySchemes(newArrayList(oauth()))
.securityContexts(newArrayList(securityContext()))
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfoBuilder()
.title(appName)
.description(appDesc)
.termsOfServiceUrl(termsOfServiceUrl)
.contact(contactName)
.version(appVersion)
.build();
return apiInfo;
}
@Bean
SecurityScheme apiKey() {
return new ApiKey(appName, appKey, "header");
}
@Bean
SecurityContext securityContext() {
AuthorizationScope[] scopes = new AuthorizationScope[]{new AuthorizationScope(scopeCode, scopeDesc)};
SecurityReference securityReference = SecurityReference
.builder()
.reference(type)
.scopes(scopes)
.build();
return SecurityContext
.builder()
.securityReferences(newArrayList(securityReference))
.forPaths(PathSelectors.any())//ant("/api/**") // 最好是能够统一前缀
.build();
}
@Bean
SecurityScheme oauth() {
return new OAuthBuilder()
.name(type)
.grantTypes(grantTypes())
.scopes(scopes())
.build();
}
List<AuthorizationScope> scopes() {
return newArrayList(new AuthorizationScope(scopeCode, scopeDesc));
}
List<GrantType> grantTypes() {
List<GrantType> grants = newArrayList(new AuthorizationCodeGrant(
new TokenRequestEndpoint(authorizationUrl, authClientId, authClientSecret),
new TokenEndpoint(tokenUrl, tokenName)));
return grants;
}
@Bean
public SecurityConfiguration securityInfo() {
return new SecurityConfiguration(authClientId, authClientSecret, scopeCode,
appKey, appKey, ApiKeyVehicle.HEADER, "", ",");
}
}
基础的配置是对整个API文档的描述以及一些全局性的配置,对所有接口起作用。这里涉及到两个注解:
@Configuration是表示这是一个配置类,是JDK自带的注解,前面的文章中也已做过说明。
@EnableSwagger2的作用是启用Swagger2相关功能。 在这个配置类里面我么实例化了一个Docket对象,这个对象主要包括三个方面的信息:
(1)整个API的描述信息,即ApiInfo对象包括的信息,这部分信息会在页面上展示。
(2)指定生成API文档的包名。
(3)指定生成API的路径。按路径生成API可支持四种模式,这个可以参考其源码:
2.3 WebMvcConfig
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
/**
* 将Swagger2 的swagger-ui.html加入资源路径下,否则Swagger2静态页面不能访问。要想使资源能够访问,可以有两种方法
* 一:需要配置类继承WebMvcConfigurationSupport 类,实现addResourceHandlers方法。
* 但是实现了WebMvcConfigurationSupport以后,Spring Boot的 WebMvc自动配置就会失效,具体表现比如访问不到
* 静态资源(js,css等)了,这是因为WebMvc的自动配置都在WebMvcAutoConfiguration类中,但是类中有这个注解
* @ConditionalOnMissingBean({WebMvcConfigurationSupport.class}),意思是一旦在容器中检测到
* WebMvcConfigurationSupport这个类,WebMvcAutoConfiguration类中的配置都不生效。
* 所以一旦我们自己写的配置类继承了WebMvcConfigurationSupport,相当于容器中已经有了WebMvcConfigurationSupport,
* 所有默认配置都不会生效,都得自己在配置文件中配置。
* 二:继承WebMvcConfigurer接口,这里采用此方法 网上有人说使用该方法会导致date编译等问题,可能在配置文件中得到解决,
* 本人没有碰到,不多做解释
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
2.4 ResourceServerConfiguration
@Configuration
@EnableResourceServer
@Order(100)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
private RedisConnectionFactory connectionFactory;
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers(StaticParams.SWAGGERUI.getSwaggerResource()).permitAll()
.anyRequest().authenticated();
// 设置通用的session创建策略
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}
@Bean
public TokenStore tokenStore() {
return new RedisTokenStore(connectionFactory);
}
}
2.5 StaticParams
public class StaticParams {
public static class USERROLE {
public static final String ROLE_ADMIN = "ROLE_ADMIN";
public static final String ROLE_USER = "ROLE_USER";
public static final String ROLE_SUPER = "ROLE_SUPER";
}
public static class PATHREGX {
private final static String getPathRex(String path) {
return "/" + path + "/**";
}
public static final String ALL = getPathRex(PATH.ALL);
public static final String VIEW = getPathRex(PATH.VIEW);
public static final String ADMIN = getPathRex(PATH.ADMIN);
public static final String API = getPathRex(PATH.API);
public static final String RESOURCE = getPathRex(PATH.RESOURCE);
public static final String STATIC = getPathRex(PATH.STATIC);
public static final String JS = getPathRex(PATH.JS);
public static final String CSS = getPathRex(PATH.CSS);
public static final String IMG = getPathRex(PATH.IMG);
}
public static class PATH {
public static final String ALL = "**";
public static final String VIEW = "view";
public static final String ADMIN = "admin";
public static final String API = "api";
public static final String RESOURCE = "resource";
public static final String STATIC = "static";
public static final String JS = "js";
public static final String CSS = "css";
public static final String IMG = "img";
public static final String WEBSOCKET_SERVICE = "websocket-service";
public static final String WEBSOCKET = "websocket";
}
/**
*
* @Package: com.jb.auth.sso<br>
* @ClassName: SWAGGERUI<br>
* @Description: swagger限制地址<br>
*/
public static class SWAGGERUI {
public static final String MAIN = "/**/swagger-ui.html";
public static final String RESOURCES = "/**/swagger-resources/**";
public static final String API_DOCS = "/**/api-docs";
public static final String STATIC_RESOURCES = "/**/webjars/springfox-swagger-ui/**";
/**
*
* @Title: getSwaggerResource
* @Description: 获取swagger对应ui资源
* @return
*/
public static String[] getSwaggerResource() {
return new String[] { MAIN, RESOURCES, API_DOCS, STATIC_RESOURCES};
}
}
}
2.6 API接口
@ApiOperation("基于分页查询计算点")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "页码", paramType = "query", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "size", value = "条数", paramType = "query", required = true, dataType = "Integer")
})
@RequestMapping(path = "/_all/_page", method = RequestMethod.GET)
@ResponseStatus(code = HttpStatus.OK)
public InvokeResult<Page<Rule>> findRuleByQueryPage(@RequestParam("page") Integer page,
@RequestParam("size")Integer size) {
CheckUtil.CheckPageIndexAndSizeAsException(page,size);
Page<Rule> ruleCriteria = service.findRuleCriteria(page,size);
return InvokeResultUtil.ofSuccessful(ruleCriteria);
}
@ApiOperation() 用于方法;表示一个http请求的操作 value用于方法描述 notes用于提示内容 tags可以重新分组(视情况而用)
@ApiModel: 用于类,表示对类进行说明,用于参数用实体类接收;
@ApiModelProperty()用于方法,字段; 表示对model属性的说明或者数据操作更改
value–字段说明
name–重写属性名字
dataType–重写属性类型
required–是否必填
example–举例说明 hidden–隐藏
@ApiImplicitParams:用在方法上包含一组参数说明
@ApiImplicitParam: 用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
paramType:参数放在哪个地方
header 请求参数的获取:@RequestHeader
query 请求参数的获取:@RequestParam
path(用于restful接口)请求参数的获取:@PathVariabl
body(不常用)
form(不常用)
name:参数名
dataType:参数类型
required:参数是否必须传
value:参数的意思
defaultValue:参数的默认值
2.7 application.yml配置
security:
userOauth:
clientId: f1autoauth
clientSecret: f1autoauthsecret
type: oauth2
authorizationUrl: http://192.168.1.23:9080/uaa/oauth/authorize
tokenUrl: http://192.168.1.23:9080/uaa/oauth/token
tokenName: access_token
scope:
code: write
desc: write
app:
key: swagger
name: Stark平台在线API
desc: 详情http://192.168.1.173/F1-IoT/stark
version: 1.0.0
termsOfServiceUrl: http://192.168.1.173/F1-IoT/stark
contact:
name: 大数据组
2.8 swagger测试接口
在Chrome浏览器中输入地址:http://ip:port/swagger-ui.html,即可打开swagger-ui界面测试接口。