我有一个用 Java 实现的 rest API(来自 swagger 的 MSF4J 代码生成)和一个描述它的 swagger 2 定义。swagger UI 托管在 Web 服务器上。API 部署在 Internet 上某处的 VM 上。
我的问题是招摇 UI 的“试用”功能不起作用。我总是收到“401 Unauthorized”。当我从 UI 中获取 curl 命令并将其粘贴到我的终端时,它可以工作。
上周我没有使用 HTTPS 或基本身份验证——只有 HTTP——它运行良好。现在我不知道为什么它不起作用。
由于我将 swagger 定义更改为 https,因此 UI 会发出 OPTIONS 请求。我实现了这一点,但我得到了 401 响应。
该证书来自 Lets Encrypt,并由 apache Web 服务器使用。apache 是同一台机器上其余 api 的代理。
这是我的身份验证拦截器:
public class BasicAuthSecurityInterceptor extends AbstractBasicAuthSecurityInterceptor {
@Override
protected boolean authenticate(String username, String password) {
if (checkCredentials(username, password))
return true;
return false;
}
private boolean checkCredentials(String username, String password) {
if (username.equals("testuser"))
return BCrypt.checkpw(password, "$2a$10$iXRsLgkJg3ZZGy4utrdNyunHcamiL2RmrKHKyJAoV4kHVGhFv.d6G");
return false;
}
}
这是api的一部分:
public abstract class DeviceApiService {
private static final Logger LOGGER = LogManager.getLogger();
public abstract Response deviceGet() throws NotFoundException;
public abstract Response deviceIdAvailableLoadGet(Integer id, Long from, Long to, String resolution)
throws NotFoundException;
public abstract Response deviceIdGet(Integer id) throws NotFoundException;
protected Response getOptionsResponse() {
String allowedOrigin = "";
try {
allowedOrigin = PropertyFileHandler.getInstance().getPropertyValueFromKey("api.cors.allowed");
} catch (IllegalArgumentException | PropertyException | IOException e) {
LOGGER.error("Could not get allowed origin.", e);
}
Response response = Response.ok().header("Allow", "GET").header("Access-Control-Allow-Origin", allowedOrigin)
.header("Access-Control-Allow-Headers", "authorization, content-type").build();
return response;
}
}
public class DeviceApi {
private final DeviceApiService delegate = DeviceApiServiceFactory.getDeviceApi();
// @formatter:off
@GET
@Produces({ "application/json" })
@io.swagger.annotations.ApiOperation(
value = "Get devices",
notes = "",
response = Device.class,
responseContainer = "List",
authorizations = { @io.swagger.annotations.Authorization(value = "basicAuth") },
tags = { "Device", }
)
@io.swagger.annotations.ApiResponses(
value = { @io.swagger.annotations.ApiResponse(
code = 200,
message = "200 OK",
response = Device.class,
responseContainer = "List")
})
public Response deviceGet() throws NotFoundException {
return delegate.deviceGet();
}
@OPTIONS
@Consumes({ "application/json" })
@Produces({ "application/json" })
@io.swagger.annotations.ApiOperation(value = "CORS support", notes = "", response = Void.class, authorizations = {
@io.swagger.annotations.Authorization(value = "basicAuth") }, tags = { "Device", })
@io.swagger.annotations.ApiResponses(value = {
@io.swagger.annotations.ApiResponse(code = 200, message = "Default response for CORS method", response = Void.class) })
public Response deviceOptions() throws NotFoundException {
return delegate.getOptionsResponse();
}
}
编辑:
这是 swagger ui 创建的请求的标头:
Accept: text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: de,en-US;q=0.7,en;q=0.3
Access-Control-Request-Headers: authorization
Access-Control-Request-Method: GET
Connection: keep-alive
DNT: 1
Host: api.myfancyurl.com
Origin: http://apidoc.myfancyurl.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/61.0
似乎缺少授权标头。当我编辑请求并使用授权标头和编码凭据重新发送它时,它可以工作。但是我不知道为什么swagger不添加这个标题。是否应该在未经授权的情况下接受所有选项请求?