preface

Scenario: Control access to video files on disk because the video may contain sensitive information and therefore cannot be freely accessed by anyone.

Train of thought

  • Access to video

    The video file is stored in a special disk directory. How can I access the video? Virtual path mapping can be configured in SpringBoot, using the ResourceHandlerRegistry to map local disk paths to urls.

  • Access control

    Filter is used for access control to intercept the mapped URL and verify the access permission.

implementation

Access to video

  • Define the configuration

    video-access:
      enable: true
      # url does not end with /
      url: /video
      # location ends with /
      location: G:/tmp/video-access/
      # IP whitelist
      whiteList:
        - 192.168. *. *
      # IP blacklist
      blackList:
    Copy the code
    @Data
    @ConfigurationProperties(prefix = "video-access")
    @Component
    public class VideoAccessConfig {
    
        // Whether to enable access verification
        private boolean enable = true;
    
        / / map urls
        private String url = "";
    
        // Video file path
        private String location = "";
        
        // IP whitelist
        private Set<String> whiteList = new HashSet<>(8);
    
        // IP blacklist
        private Set<String> blackList = new HashSet<>(8);
    
        public Set<String> getWhiteList(a) {
          // The local is added to the whitelist by default
          whiteList.add("127.0.0.1");
          whiteList.add("0:0:0:0:0:0:0:1");
          returnwhiteList; }}Copy the code
  • Add the mapping

    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        @Autowired
        private VideoAccessConfig videoAccessConfig;
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler(videoAccessConfig.getUrl() + "/ * *")
                    .addResourceLocations("file:"+ videoAccessConfig.getLocation()); }}Copy the code

Access control

  • Access mechanism

    • ipWhether it is in the whitelistwhiteListIn the skip
    • ipWhether it is in the blacklistblackListIn refusing to
    • Custom access control logic
  • Define the Filter

    @Component
    public class VideoAccessFilter extends OncePerRequestFilter {
    
        @Autowired
        private VideoAccessConfig videoAccessConfig;
        
        private AntPathMatcher antPathMatcher = new AntPathMatcher();
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
           // Get the IP address here; The real IP can be obtained from the request header
            String ip = request.getRemoteAddr(); 
            // Whitelist allowed
            Set<String> whiteList = accessControlConfig.getWhiteList();
            boolean ignored = whiteList.stream().anyMatch(item -> antPathMatcher.match(item, ip));
            if (ignored) {
                filterChain.doFilter(request, response);
                return;
            }
    		// Blacklist blocking
            Set<String> blackList = accessControlConfig.getBlackList();
            boolean blocked = blackList.stream().anyMatch(item -> antPathMatcher.match(item, ip));
            if (blocked) {
                reject(response);
                return;
            }
            
            // TODO:Customize the access control logic here
            String token = httpServletRequest.getQueryString();
            if (videoAccessConfig.isEnable() && Objects.isNull(token)) {
                reject(response);
                return;
            }
            
            filterChain.doFilter(request, response);
        }
        private void reject(HttpServletResponse response) throws IOException {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.getOutputStream().write("Access Denied".getBytes(StandardCharsets.UTF_8)); response.getOutputStream().close(); }}Copy the code
  • Intercepts the URL and registers the Filter with the FilterRegistrationBean

    
    @Autowired
    private VideoAccessFilter videoAccessFilter;
    
    @Bean
    public FilterRegistrationBean filterOneRegister(a) {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>();
            filterRegistrationBean.setFilter(videoAccessFilter);
            filterRegistrationBean.addUrlPatterns(videoAccessConfig.getUrl() + "/ *");
            return filterRegistrationBean;
        }
    Copy the code

test

Map image path for easy testing, test URL containing queryString indicates permission

  • Mapping folder

  • Without permissionhttp://localhost:8080/video/miruiki.jpg

  • Have permissionhttp://localhost:8080/video/miruiki.jpg?token=1231

At the end

If this article is helpful to you, please like 👍🏻 to support it. If there is any mistake or better suggestion, welcome to correct, thank you.