在我的Spring启动应用程序中,我在/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
时,我得到 401 错误,这不是我想要的是。我希望用户可以使用index.html
。
答案 0 :(得分:2)
您可以检查X-Requested-With
标题:
private boolean isAjax(HttpServletRequest request) {
String requestedWithHeader = request.getHeader("X-Requested-With");
return "XMLHttpRequest".equals(requestedWithHeader);
}
更新:也许这是检查Accept
标头的更好方法。我认为浏览器包含Accept: text/html
标题而非脚本等的概率要高得多,包括X-Requested-With
标题。
如果Accept: text/html
标题存在,您可以创建自定义身份验证入口点并重定向用户:
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
),则不会调用身份验证入口点。您可以使用unsuccessfulAuthentication()
的{{1}}方法处理重定向。
<强>备选方案:强>
AbstractAuthenticationProcessingFilter
并处理BasicErrorController
错误的重定向。401 Unauthorized
调用上返回JSON,否则返回html?答案 1 :(得分:2)
所以,我最终通过修复我的安全配置解决了这个问题:
我有一个自定义JWTAuthenticationFilter
,其中我覆盖了unsuccessfulAuthentication
方法:
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
logger.debug("failed authentication while attempting to access "+ URL_PATH_HELPER.getPathWithinApplication((HttpServletRequest) request));
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.sendRedirect("/");
}
如您所见,如果身份验证失败,我会将用户重定向到&#34; /&#34;作为回报,将由资源解析器捕获,index.html
将被提供!
答案 2 :(得分:1)
浏览器通常设置&#34; User-Agent&#34; http请求的标头。
因此,您可以使用以下命令区分这些调用:request.getHeader(&#34; User-Agent&#34;);
另见: