内容概述
本文次要介绍下,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
- 用来保留session数据的类,配置将session保留在redis中时,应用的就是
HttpSessionIdResolver
- 负责从HTTP申请中解析出sessionid。默认应用的是
CookieHttpSessionIdResolver
,能够看出是从cookie中解析。 - 还有一个实现类是
HeaderHttpSessionIdResolver
,由此能够看出还能够将sessionid保留在header中。
- 负责从HTTP申请中解析出sessionid。默认应用的是
当然也能够实现一个本人的过滤器,次要有两种形式:
实现
Filter
接口,并应用@WebFilter
注解- 上面咱们的实现中继承了
OncePerRequestFilter
这个类,这个类也是Filter
接口的实现类,封装了一些性能,应用更不便。
- 上面咱们的实现中继承了
- 写一个创立@Bean的办法,返回
FilterRegistrationBean
的对象。
上面咱们应用第一种形式实现一个限度指定IP的过滤器:
/** * ip黑名单 */@WebFilterpublic 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的信息。
一个简略的拦截器实现如下:
@Componentpublic 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(); }}
定义之后要注册到解决流程中:
@Configurationpublic 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。这样看单个拦截器的范畴比过滤器要小很多。
以上内容属集体学习总结,如有不当之处,欢送在评论中斧正