目录
一、前言
Swagger方便开发和联调,同时也会存在接口安全问题。所以在生产环境是禁止开放Swagger的,或者更严格一点,SIT、UAT都必须授权访问,Swagger安全方式通常有几种:
-
在Swagger接口中添加认证授权机制,例如JWT令牌和OAuth2.0认证。参考:https://www.jianshu.com/p/431eb71bd79e
-
使用Spring Security框架进行安全管理,针对Swagger接口添加相应的权限配置和拦截器。
-
进行IP访问控制,只允许特定的IP地址访问Swagger接口。
-
对Swagger接口进行加密,例如使用SSL证书或TLS协议进行数据加密传输。
-
使用HTTPS协议访问Swagger接口,以防止中间人攻击和窃取数据。
我个人是偏向第3种,配置一下ip地址就可以了
二、配置swagger开关
2.1、配置文件
在application-prod.properties添加
swagger.enable=false
2.2、配置SwaggerConfig
在SwaggerConfig加上注解@ConditionalOnProperty
@ConditionalOnProperty(name = "swagger.enable", havingValue = "true")
public class SwaggerConfig {
这样prod环境就不会显示swagger了
三、按ip授权
3.1、新增一个拦截器
工具类,这里我当它父类使用,用于返回json信息
public class CommonTokenHandler {
/**
* 返回错误信息
* @param httpResponse
* @param status
* @param msg
* @param request
* @throws Exception
*/
public void setReturn(HttpServletResponse httpResponse, int status, String msg, HttpServletRequest request) throws Exception {
PrintWriter writer = null;
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpResponse.setHeader("Access-Control-Allow-Origin", request.getAttribute("Access-Control-Allow-Origin") == null?null:request.getAttribute("Access-Control-Allow-Origin").toString());
//UTF-8编码
httpResponse.setCharacterEncoding("UTF-8");
httpResponse.setContentType("application/json;charset=utf-8");
Map<String, Object> result = new HashMap<>();
result.put("code", status);
result.put("msg", msg);
JSONObject jsonObject = new JSONObject(result);
String json = jsonObject.toString();
try {
writer = httpResponse.getWriter();
writer.print(json);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (writer != null){
writer.close();
}
}
}
}
拦截器继承CommonTokenHandler
@Component
@Slf4j
public class SwaggerHandler extends CommonTokenHandler implements HandlerInterceptor {
@Autowired
private RedisUtil redisUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
log.info("requestURI = {}", requestURI);
String ipAddr = IpUtils.getIpAddr(request);
log.info("请求IP....{}", ipAddr);
if (Objects.toString(ipAddr).equals("127.0.0.1")) {
return true;
}
// 这里是自定义redis的key
Object key = redisUtil.get(RedisKeyUtil.swaggerIP());
if (key == null || !key.toString().contains(ipAddr)) {
String msg = "您的IP" + ipAddr + "没有访问swagger的权限,请先配置!";
log.info(msg);
setReturn( response, 7002, msg, request);
return false;
}
return true;
}
}
ip工具类
public class IpUtils {
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
if (request != null) {
// X-Forwarded-For:Squid 服务代理
String ipAddresses = request.getHeader("X-Forwarded-For");
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
// Proxy-Client-IP:apache 服务代理
ipAddresses = request.getHeader("Proxy-Client-IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
// WL-Proxy-Client-IP:weblogic 服务代理
ipAddresses = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
// HTTP_CLIENT_IP:有些代理服务器
ipAddresses = request.getHeader("HTTP_CLIENT_IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
// X-Real-IP:nginx服务代理
ipAddresses = request.getHeader("X-Real-IP");
}
// 有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
if (ipAddresses != null && ipAddresses.length() != 0) {
ip = ipAddresses.split(",")[0];
}
// 还是不能获取到,最后再通过request.getRemoteAddr();获取
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
ip = request.getRemoteAddr();
}
return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
}
return null;
}
}
3.2、使用拦截器
新增拦截器配置类MyWebAppConfigurer,将swaggerHandler添加到拦截器链,对doc.html、swagger-ui.html同时拦截
@Configuration
@AutoConfigureOrder(-1)
public class MyWebAppConfigurer implements WebMvcConfigurer {
@Autowired
private SwaggerHandler swaggerHandler;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// addPathPatterns 用于添加拦截规则
// excludePathPatterns 用户排除拦截
registry.addInterceptor(swaggerHandler).addPathPatterns("/**/doc.html/**", "/**/swagger-ui.html/**","/swagger-resources/**","/swagger-ui/**");
}
/**
* 修改StringHttpMessageConverter默认配置
*
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
}
3.3、验证
未放行之前
添加放行ip
再次验证