导读


由于项目需要,这里需要设计一个IP白名单,增加接口安全。SpringBoot项目,因为接口已经开发好,在不变动接口的情况下,采用拦截器做处理,思路是拦截指定的请求,获取到该请求的IP,然后根据该ip去数据库查询是否存在,如果存在就允许访问,否则没有权限访问。(PS:拦截器可以通过访问Service层,在service层添加Redis缓存,设置下缓存失效时间,这样就不需要每次访问接口就从数据库中查一遍,减轻数据库访问压力,点击查看Redis缓存配置,目前这里未设置Redis缓存)

使用


创建表ip_filter

  1. CREATE TABLE `ip_filter` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '序号',
  3. `ip` varchar(255) NOT NULL COMMENT 'ip地址',
  4. `whitelists` tinyint(4) NOT NULL COMMENT '白名单0:黑名单1',
  5. `module` varchar(255) DEFAULT NULL COMMENT '模块',
  6. `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  7. `modify_time` datetime DEFAULT NULL COMMENT '修改时间',
  8. PRIMARY KEY (`id`)
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='IP白名单表';

创建实体类和Mapper查询接口

  • 实体类IpFilter ```java

/**

  • ip过滤器实体类 */ @Data public class IpFilter implements Serializable {

    private static final long serialVersionUID = 8802493743077425037L; /**

    • ip地址 */ private String ip;

      /**

    • 白名单—0,黑名单—1 */ private Integer whitelists;

      /**

    • 模块 */ private String module;

      /**

    • 创建时间 */ private Date createTime;

      /**

    • 修改时间 */ private Date modifyTime; }
  1. - **Mapper接口IpFilterMapper**
  2. ```java
  3. import com.demo.common.entity.IpFilter;
  4. import org.apache.ibatis.annotations.*;
  5. import org.springframework.stereotype.Component;
  6. import java.util.List;
  7. @Mapper
  8. @Component
  9. public interface IpFilterMapper {
  10. /**
  11. * 从数据库中查询IP是否存在
  12. *
  13. * @param ipFilter
  14. * @return
  15. */
  16. @Select("select * from ip_filter where ip = #{query.ip} and whitelists=#{query.whitelists}")
  17. @Results(
  18. id = "ipFilterMessage",
  19. value = {
  20. @Result(column = "ip", property = "ip"),
  21. @Result(column = "module", property = "module"),
  22. @Result(column = "whitelists", property = "whitelists"),
  23. @Result(column = "create_time", property = "createTime"),
  24. @Result(column = "modifyTime", property = "modify_time")
  25. }
  26. )
  27. List<IpFilter> selectIpFilterByRealIp(@Param("query") IpFilter ipFilter);
  28. }

获取工具类IPUtils

  1. import javax.servlet.http.HttpServletRequest;
  2. /**
  3. * 获取用户的IP
  4. */
  5. public class IPUtils {
  6. /**
  7. * 本地IP localhost
  8. */
  9. private static final String NATIVEIP = "0:0:0:0:0:0:0:1";
  10. /**
  11. * 获取用户真实IP地址,不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址,
  12. * 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值
  13. *
  14. * @return ip
  15. */
  16. public static String getRealIP(HttpServletRequest request) {
  17. String ip = request.getHeader("x-forwarded-for");
  18. if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
  19. // 多次反向代理后会有多个ip值,第一个ip才是真实ip
  20. if (ip.indexOf(",") != -1) {
  21. ip = ip.split(",")[0];
  22. }
  23. }
  24. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  25. ip = request.getHeader("Proxy-Client-IP");
  26. System.out.println("Proxy-Client-IP ip: " + ip);
  27. }
  28. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  29. ip = request.getHeader("WL-Proxy-Client-IP");
  30. System.out.println("WL-Proxy-Client-IP ip: " + ip);
  31. }
  32. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  33. ip = request.getHeader("HTTP_CLIENT_IP");
  34. System.out.println("HTTP_CLIENT_IP ip: " + ip);
  35. }
  36. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  37. ip = request.getHeader("HTTP_X_FORWARDED_FOR");
  38. System.out.println("HTTP_X_FORWARDED_FOR ip: " + ip);
  39. }
  40. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  41. ip = request.getHeader("X-Real-IP");
  42. System.out.println("X-Real-IP ip: " + ip);
  43. }
  44. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  45. ip = request.getRemoteAddr();
  46. System.out.println("getRemoteAddr ip: " + ip);
  47. }
  48. if (ip.equals(NATIVEIP)) {
  49. ip = "127.0.0.1";
  50. System.out.println("get native ip" + ip);
  51. }
  52. return ip;
  53. }
  54. }

拦截器IPInterceptor

  1. import com.demo.common.entity.IpFilter;
  2. import com.demo.common.mapper.IpFilterMapper;
  3. import com.demo.common.utils.IPUtils;
  4. import org.apache.commons.lang3.StringUtils;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.stereotype.Component;
  9. import org.springframework.web.servlet.HandlerInterceptor;
  10. import org.springframework.web.servlet.ModelAndView;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13. import java.util.List;
  14. /**
  15. * IP 拦截器
  16. */
  17. @Component
  18. public class IPInterceptor implements HandlerInterceptor {
  19. private static Logger LOG = LoggerFactory.getLogger(IPInterceptor.class);
  20. @Autowired
  21. private IpFilterMapper ipFilterMapper;
  22. @Override
  23. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  24. //过滤ip,若用户在白名单内,则放行
  25. String ipAddress = IPUtils.getRealIP(request);
  26. LOG.info("USER IP ADDRESS IS =>" + ipAddress);
  27. if (!StringUtils.isNotBlank(ipAddress)) {
  28. return false;
  29. }
  30. IpFilter ipFilter = new IpFilter();
  31. //可以访问模块
  32. ipFilter.setModule("test");
  33. //ip地址
  34. ipFilter.setIp(ipAddress);
  35. //白名单
  36. ipFilter.setWhitelists(0);
  37. List<IpFilter> ips = ipFilterMapper.selectIpFilterByRealIp(ipFilter);
  38. if (ips.isEmpty()) {
  39. response.getWriter().append("<h1 style=\"text-align:center;\">Not allowed!</h1>");
  40. return false;
  41. }
  42. return true;
  43. }
  44. @Override
  45. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  46. }
  47. @Override
  48. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  49. }
  50. }

全局配置拦截

  1. import com.demo.common.interceptor.IPInterceptor;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.servlet.config.annotation.CorsRegistry;
  5. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  7. @Configuration
  8. public class GlobalCorsConfig extends WebMvcConfigurerAdapter {
  9. @Autowired
  10. private IPInterceptor ipInterceptor;
  11. @Override
  12. public void addInterceptors(InterceptorRegistry registry) {
  13. // 添加拦截器,配置拦截地址,这里拦截以api请求的接口比如http://localhost/api/getUser
  14. registry.addInterceptor(ipInterceptor).addPathPatterns("/api/**");
  15. }
  16. /**
  17. //跨域请求拦截器
  18. @Override
  19. public void addCorsMappings(CorsRegistry registry) {
  20. registry.addMapping("/**")
  21. .allowCredentials(true)
  22. .allowedHeaders("*")
  23. .allowedOrigins("*")
  24. .allowedMethods("*");
  25. }*/
  26. }

END


这里还没有做限流处理,下次考虑试下限流。