gpt4 book ai didi

java - Spring 将浏览器访问者与对端点的 API 调用区分开来

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:22:10 34 4
gpt4 key购买 nike

在我的 Spring boot 应用程序中,我在 /api/** 有一堆端点。以下是我的 App 配置:

@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {

private class PushStateResourceResolver implements ResourceResolver {
private Resource index = new ClassPathResource("/public/index.html");
private List<String> handledExtensions = Arrays.asList("html", "js",
"json", "csv", "css", "png", "svg", "eot", "ttf", "woff",
"appcache", "jpg", "jpeg", "gif", "ico");

private List<String> ignoredPaths = Arrays.asList("^api\\/.*$");

@Override
public Resource resolveResource(HttpServletRequest request,
String requestPath, List<? extends Resource> locations,
ResourceResolverChain chain) {
return resolve(requestPath, locations);
}

@Override
public String resolveUrlPath(String resourcePath,
List<? extends Resource> locations, ResourceResolverChain chain) {
Resource resolvedResource = resolve(resourcePath, locations);
if (resolvedResource == null) {
return null;
}
try {
return resolvedResource.getURL().toString();
} catch (IOException e) {
return resolvedResource.getFilename();
}
}

private Resource resolve(String requestPath,
List<? extends Resource> locations) {
if (isIgnored(requestPath)) {
return null;
}
if (isHandled(requestPath)) {
return locations
.stream()
.map(loc -> createRelative(loc, requestPath))
.filter(resource -> resource != null
&& resource.exists()).findFirst()
.orElseGet(null);
}
return index;
}

private Resource createRelative(Resource resource, String relativePath) {
try {
return resource.createRelative(relativePath);
} catch (IOException e) {
return null;
}
}

private boolean isIgnored(String path) {
return false;
// return !ignoredPaths.stream().noneMatch(rgx -> Pattern.matches(rgx, path));
//deliberately made this change for examining the code
}

private boolean isHandled(String path) {
String extension = StringUtils.getFilenameExtension(path);
return handledExtensions.stream().anyMatch(
ext -> ext.equals(extension));
}
}
}

检查对 /api/** 后面端点的访问是否经过身份验证,因此当我在浏览器中输入 /api/my_endpoint 时,我得到 < strong>401 错误返回,这不是我想要的。我希望为用户提供 index.html

最佳答案

您可以检查 X-Requested-With header :

private boolean isAjax(HttpServletRequest request) {
String requestedWithHeader = request.getHeader("X-Requested-With");
return "XMLHttpRequest".equals(requestedWithHeader);
}

更新:也许这是检查 Accept header 的更好方法。我认为浏览器包含 Accept: text/html header 的可能性要比脚本等包含 X-Requested-With header 的可能性高得多。

如果 Accept: text/html header 存在,您可以创建自定义身份验证入口点并重定向用户:

public class CustomEntryPoint implements AuthenticationEntryPoint {

private static final String ACCEPT_HEADER = "Accept";

private final RedirectStrategy redirect = new DefaultRedirectStrategy();

@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
if (isHtmlRequest(request)) {
redirect.sendRedirect(request, response, "/");
} else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized access is not allowed");
}
}

private boolean isHtmlRequest(HttpServletRequest request) {
String acceptHeader = request.getHeader(ACCEPT_HEADER);
List<MediaType> acceptedMediaTypes = MediaType.parseMediaTypes(acceptHeader);
return acceptedMediaTypes.contains(MediaType.TEXT_HTML);
}

}

注意:

如果您使用自定义身份验证过滤器(继承自 AbstractAuthenticationProcessingFilter),则不会调用身份验证入口点。您可以在 AbstractAuthenticationProcessingFilterunsuccessfulAuthentication() 方法中处理重定向。

备选方案:

  • 覆盖 Spring Boot 的标准 BasicErrorController 并在那里处理 401 Unauthorized 错误的重定向。
  • 为什么不在所有 /api 调用上返回 JSON 而在其他情况下返回 html?

关于java - Spring 将浏览器访问者与对端点的 API 调用区分开来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47735118/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com