2017-12-10 69 views
9

मेरे स्प्रिंग बूट ऐप में, मेरे पास /api/** पर एंडपॉइंट्स का गुच्छा है। निम्नलिखित मेरी अनुप्रयोग विन्यास है:एपीआई कॉल से ब्राउज़र आगंतुकों को अंतराल पर

@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 में टाइप करें, मैं त्रुटि वापस पाने, जो मैं क्या नहीं है चेक किया गया है चाहते हैं। मैं चाहता हूं कि उपयोगकर्ता index.html के साथ सेवा करें।

+1

आप सभी अनुरोधों के लिए एक इंटरसेप्टर या फ़िल्टर का उपयोग कर सकते हैं, और प्रतिक्रिया और पथ की जांच कर सकते हैं और इसके अनुसार कार्य नहीं कर सकते हैं? – DvTr

उत्तर

2

तो, मैं अंत में इस मुद्दे को मेरी सुरक्षा config फिक्सिंग द्वारा हल विफल रहता है, मैं उपयोगकर्ता को "/" पर रीडायरेक्ट करता हूं जो बदले में संसाधन रिज़ॉल्वर द्वारा पकड़ा जाएगा और index.html परोसा जाएगा!

+0

अच्छा है कि आपने अपनी समस्या का समाधान किया है। कृपया अगली बार अधिक जानकारी दें, उदा। कि आप एक कस्टम प्रमाणीकरण फ़िल्टर का उपयोग करें। – Christian

1

ब्राउज़र आमतौर पर http अनुरोध के "उपयोगकर्ता-एजेंट" शीर्षलेख सेट करते हैं।

तो आप इन कॉलों का उपयोग करके इन अनुरोधों को अलग कर सकते हैं: request.getHeader ("उपयोगकर्ता-एजेंट");

यह भी देखें:

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()AbstractAuthenticationProcessingFilter की विधि में संभाल सकते हैं।

विकल्प:

  • अवहेलना स्प्रिंग बूट के मानक BasicErrorController और वहाँ 401 Unauthorized त्रुटियों की अनुप्रेषित संभाल।
  • क्यों नहीं सभी /api कॉल और एचटीएमएल पर जेएसओएन वापस क्यों न करें?

    मैं एक कस्टम 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("/"); 
    } 
    

    आप देख सकते हैं, अगर प्रमाणीकरण

संबंधित मुद्दे