这次总结的内容为通过spring-security实现的OAuth2+JWT认证服务器和资源服务器分离架构下,如何引入swagger+feign。
需要解决的问题:
1、swagger-ui.html不需要权限验证
2、swagger需要提供request头的Authorization参数的输入框来输入令牌
3、通过feign调用其他微服务时,被调用服务不再需要权限认证
一、swagger-ui.html绕过权限验证
这个问题解决起来比较简单,由于这里使用的是spring-security,那么只需要在认证服务器的安全配置中绕过相关的资源即可
.antMatchers(
Constants.LOGIN_CONTROLLER,
Constants.IMAGE_CODE_CONTROLLER+"/**",
Constants.SMS_CODE_CONTROLLER+"/**",
"/swagger-ui.html",
"/swagger-resources/**",
"/v2/api-docs",
"/oauth/check_token").permitAll()
二、swagger提供request头的Authorization参数输入框
这个问题也好解决,两个办法,一个是每个rest api上进行注释声明,一个是通过java config统一进行配置。第一种方法没什么好说的,这里说说第二种方法,只需要做如下配置即可
@Bean
public Docket createRestApi() {
ParameterBuilder authorizationPar = new ParameterBuilder();
List pars = new ArrayList();
authorizationPar.name("Authorization").description("Authorization")
.modelRef(new ModelRef("string")).parameterType("header")
.required(false).build();
pars.add(authorizationPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(MultiRequestHandlerSelectors.basePackage(serverCoreProperties.getSwagger().getBasePackages()))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(pars);
}
三、微服务间通过feign调用时,被调用服务绕过权限验证
思路是这样的,通过feign调用其他服务的时候,调用一个拦截器,在拦截器中把token传入request头的Authorization参数中。这里的拦截器为feign.RequestInterceptor,实现代码举例如下
public class SsoFeignConfig implements RequestInterceptor {
public static String TOKEN_HEADER = "authorization";
@Override
public void apply(RequestTemplate template) {
template.header(TOKEN_HEADER, getHeaders(getHttpServletRequest()).get(TOKEN_HEADER));
}
private HttpServletRequest getHttpServletRequest() {
try {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
} catch (Exception e) {
return null;
}
}
private Map getHeaders(HttpServletRequest request) {
Map map = new LinkedHashMap<>();
Enumeration enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
return map;
}
}
在调用方声明微服务的时候通过@FeignClient注释的configuration属性指定拦截器
@FeignClient(name="user-server/userApi", fallback=UserServiceImpl.class, configuration = SsoFeignConfig.class)
public interface UserService {
@GetMapping("/user/name/{username}")
public SimpleResponse getByusername(@PathVariable("username") String username);
}
@FeignClient中的name为微服务的服务名+微服务的contextPath,fallback为服务调用失败的处理类,configuration用来指定拦截器
到此为止,OAuth2+JWT模式下的swagger+feign处理就完成了