乐趣区

关于java:SpringBoot系列4session和鉴权过滤器和拦截器

内容概述

本文次要介绍下,SpringBoot 的 web 我的项目中,

  • 申请中 session 是如何被解决的 – 过滤器
  • 鉴权的实现原理 – 拦截器
  • 过滤器和拦截器的比照和利用场景

1.session 是如何被解决的 – 过滤器

应用 redis 保留并共享 session,能够实现集群内的登录信息共享。SpringBoot 我的项目中,通过在 application.yml 减少 redis 的配置,即可实现对 session 的存储和批改。

那么 session 是在何时被解决的?session 的 key 又是如何生成的呢?这里理论应用了 web 我的项目中的过滤器。

在 SpringBoot 的 web 我的项目中,启动的 tomcat 在解决 http 申请时,有一个很重要的类:ApplicationFilterChain。每个 http 申请在解决时都会通过这个类。这个类负责按程序解决全副已注册的 Filter,也就是过滤器。通过实现 tomcat 中的Filter 接口,就能够定义一个过滤器。

在 SpringBoot 中的 web 我的项目中,有几个默认的过滤器,其中一个就是用来解决 session 的:SessionRepositoryFilter

SessionRepositoryFilter次要的成员是两个接口,都有多个可选的实现类,通过这两个成员就实现了对 session 的解析。

  • SessionRepository

    • 用来保留 session 数据的类,配置将 session 保留在 redis 中时,应用的就是RedisIndexedSessionRepository
  • HttpSessionIdResolver

    • 负责从 HTTP 申请中解析出 sessionid。默认应用的是CookieHttpSessionIdResolver,能够看出是从 cookie 中解析。
    • 还有一个实现类是HeaderHttpSessionIdResolver,由此能够看出还能够将 sessionid 保留在 header 中。

当然也能够实现一个本人的过滤器,次要有两种形式:

  • 实现 Filter 接口,并应用 @WebFilter 注解

    • 上面咱们的实现中继承了 OncePerRequestFilter 这个类,这个类也是 Filter 接口的实现类,封装了一些性能,应用更不便。
  • 写一个创立 @Bean 的办法,返回 FilterRegistrationBean 的对象。

上面咱们应用第一种形式实现一个限度指定 IP 的过滤器:

/**
 * ip 黑名单
 */
@WebFilter
public class IPFilter extends OncePerRequestFilter { // 这里继承 OncePerRequestFilter

    private List<String> forbiddenIpList = new ArrayList<>();

    public IPFilter() {this.forbiddenIpList.add("10.112.13.167");
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String ip = request.getRemoteAddr();
        if (this.forbiddenIpList.contains(ip)) {response.setContentType("application/json;charset=UTF-8");
            PrintWriter out = response.getWriter();
            ObjectMapper objectMapper = new ObjectMapper();
            out.write(objectMapper.writeValueAsString(CommonResVo.fail(400, "禁止拜访的 ip")));
            out.flush();} else {filterChain.doFilter(request, response);
        }
    }
}

2. 鉴权的实现原理 – 拦截器

通过过滤器解析 session 后,就能够依据 session 中保留的内容,判断以后登录的用户权限。

这里是通过一个拦截器实现的,在拦截器中能够间接通过 HttpServletRequest.getSession() 办法间接获取 session 的信息。

一个简略的拦截器实现如下:

@Component
public class LoginAuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();
        Integer userId = (Integer) session.getAttribute("userId");
        if (userId == null) {authFailOutput(response, "登录信息不存在,请从新登录");
            return false;
        }
        return true;
    }
    /**
     * json 输入
     */
    private void authFailOutput(HttpServletResponse response, String msg) throws IOException {response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        ObjectMapper objectMapper = new ObjectMapper();
        out.write(objectMapper.writeValueAsString(CommonResVo.fail(400, msg)));
        out.flush();}
}

定义之后要注册到解决流程中:

@Configuration
public class Interceptor implements WebMvcConfigurer {

  @Resource
  HandlerInterceptor loginAuthInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
      // 增加一个拦截器,判断权限,排除掉登录接口
      registry.addInterceptor(loginAuthInterceptor)
              .excludePathPatterns("/user/login","/user/register");
  }
}

3. 过滤器和拦截器的比照和利用场景

先来看下过滤器和拦截器的执行程序,通过 debug 失去的执行程序如下图:

在大部分场景中,过滤器和拦截器都是可调换的,应用哪个都能够。

过滤器和拦截器也有些区别,这里不谈实现和标准的差别,就说下应用中可能波及的区别:

  • 执行程序不同:从上图中能够看到,过滤器是先于拦截器执行的,在组合应用实现性能时,要留神下程序。
  • 可取得的参数不同:在拦截器中,能够获取以后申请绑定的 Controller 的解决办法,通过对办法剖析能够实现一些非凡需要。比方在拦截器中按既定的格局返回空数据。

最初对于过滤器和拦截器的利用场景,说下集体的总结。基于执行程序,办法参数和 SpringBoot 中的一些实现类来看。

  • 过滤器根本是对于整个 http 申请的剖析解决,比方 ip 过滤,session 解决,header 解决等。而不是针对特定的 url,范畴比拦截器更广。简直所有的 Http 申请都要通过过滤器的解决。
  • 拦截器次要是针对一批特定的 url 做解决,不同的 url 利用不同的拦截器,例如鉴权的拦截器就不会解决注册或登录等不须要权限的 url。这样看单个拦截器的范畴比过滤器要小很多。

以上内容属集体学习总结,如有不当之处,欢送在评论中斧正

退出移动版