一、前言

  一下代码以SSO用户登录列子代码。完整代码https://gitee.com/xuxueli0323/xxl-sso

二、使用

 2.1 创建过滤器

  创建一个过滤器,实现Filter 接口

  

public class XxlSsoTokenFilter extends HttpServlet implements Filter {
private static Logger logger = LoggerFactory.getLogger(XxlSsoTokenFilter.class); private static final AntPathMatcher antPathMatcher = new AntPathMatcher(); private String ssoServer;
private String logoutPath;
private String excludedPaths; @Override
public void init(FilterConfig filterConfig) throws ServletException { ssoServer = filterConfig.getInitParameter(Conf.SSO_SERVER);
logoutPath = filterConfig.getInitParameter(Conf.SSO_LOGOUT_PATH);
excludedPaths = filterConfig.getInitParameter(Conf.SSO_EXCLUDED_PATHS); logger.info("XxlSsoTokenFilter init.");
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response; // make url
String servletPath = req.getServletPath(); // excluded path check
if (excludedPaths!=null && excludedPaths.trim().length()>0) {
for (String excludedPath:excludedPaths.split(",")) {
String uriPattern = excludedPath.trim(); // 支持ANT表达式
if (antPathMatcher.match(uriPattern, servletPath)) {
// excluded path, allow
chain.doFilter(request, response);
return;
} }
} // logout filter
if (logoutPath!=null
&& logoutPath.trim().length()>0
&& logoutPath.equals(servletPath)) { // logout
SsoTokenLoginHelper.logout(req); // response
res.setStatus(HttpServletResponse.SC_OK);
res.setContentType("application/json;charset=UTF-8");
res.getWriter().println("{\"code\":"+ReturnT.SUCCESS_CODE+", \"msg\":\"\"}"); return;
} // login filter
XxlSsoUser xxlUser = SsoTokenLoginHelper.loginCheck(req);
if (xxlUser == null) { // response
res.setStatus(HttpServletResponse.SC_OK);
res.setContentType("application/json;charset=UTF-8");
res.getWriter().println("{\"code\":"+Conf.SSO_LOGIN_FAIL_RESULT.getCode()+", \"msg\":\""+ Conf.SSO_LOGIN_FAIL_RESULT.getMsg() +"\"}");
return;
} // ser sso user
request.setAttribute(Conf.SSO_USER, xxlUser); // already login, allow
chain.doFilter(request, response);
return;
} }

  2.2 注册filter

    使用java 配置  @Configuration 注解配置 ,通过FilterRegistrationBean ,向spring容器中注入 过滤器。

 

@Configuration
public class XxlSsoConfig implements DisposableBean { @Value("${xxl.sso.server}")
private String xxlSsoServer; @Value("${xxl.sso.logout.path}")
private String xxlSsoLogoutPath; @Value("${xxl.sso.redis.address}")
private String xxlSsoRedisAddress; @Value("${xxl-sso.excluded.paths}")
private String xxlSsoExcludedPaths; @Bean
public FilterRegistrationBean xxlSsoFilterRegistration() { // xxl-sso, redis init
JedisUtil.init(xxlSsoRedisAddress); // xxl-sso, filter init
FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setName("XxlSsoWebFilter");
registration.setOrder(1);
registration.addUrlPatterns("/*");
registration.setFilter(new XxlSsoTokenFilter());
registration.addInitParameter(Conf.SSO_SERVER, xxlSsoServer);
registration.addInitParameter(Conf.SSO_LOGOUT_PATH, xxlSsoLogoutPath);
registration.addInitParameter(Conf.SSO_EXCLUDED_PATHS, xxlSsoExcludedPaths); return registration;
} @Override
public void destroy() throws Exception { // xxl-sso, redis close
JedisUtil.close();
} }

  

三、执行流程

  以springboot 为列子,看filter 是如何工作的

  3.1 bean的注入

    因为filter 以 FilterRegistrationBean 的形式 注入到spring  的容器,首先来看看这个类的结构 ,可以看到这个类实现 ServletContextInitializer 接口

        

  3.2 断点跟踪

    在FilterRegistrationBean  类中有个方法getFilter 获取的过滤器,在这里打个断点,看看spring在什么时候会来获取过滤器。

    

启动容器,进入断点 ,观察栈信息,可以看到是在创建spring容器后创建tomcat  服务进入的断点

    

    然后拿到所有接口实现,调用

    

    看下  FilterRegistrationBean 调用 onStartup  把filter获取注册到servletContext 容器中

    

    最后 封装成 FilterMap放进org.apache.catalina.core.StandardContext#filterMaps

    

    

3.3 前端断点

  在过滤器中打上断点,前端发起请求,进入断点

  

  找到 ApplicationFilterChain 看到过滤器在 org.apache.catalina.core.ApplicationFilterChain#filters 中  ,分析发现添加过滤器的方法 ,在此方法设置断点,前端再次发请求

  

  

  
  

  过滤器链创建完了之后 会调用 过滤器链,用里面的过滤器循环过滤

  

 

最新文章

  1. 记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题
  2. Objective-C_基本数据类型详解
  3. Whole life
  4. OpenCV学习笔记——OpenCV安装
  5. 看stackoverflow大牛如何回答何时在ASP.NET中使用异步控制器?
  6. VPS拨号主机自动拨号脚本(centos7)
  7. Workaround for Markdown blogging platform that to use LaTeX
  8. Different ways to invoke a shared object/share library(.so)
  9. 解决nginx负载均衡的session共享问题
  10. curl要注意的几点
  11. ACCESS-关于DELPHI中操作ACCESS数据库中单精度数据的问题
  12. 又一家自适应学习平台上线,大讲台主攻IT在线教育
  13. HDU 4604 Deque 二分最长上升子序列
  14. [转载]起动service保存android系统log( logcat服务)
  15. PL/SQL程序中调用Java代码(转)
  16. Keil C 里面Lib库文件的生成与调用
  17. mysql主键,外键,索引
  18. PHP之cookies小练习
  19. 把旧系统迁移到.Net Core 2.0 日记 (20) --使用MiniProfiler for .NET
  20. jq 绑定事件和解绑事件

热门文章

  1. Visual Studio 2019连接MySQL数据库详细教程
  2. silky微服务模块
  3. java miniui(datagrid) 取值赋值
  4. 菜鸡的Java笔记 第三十四 Annotation
  5. 说透 Docker:虚拟化
  6. 析构函数与this指针
  7. 『与善仁』Appium基础 — 14、Appium测试环境搭建
  8. 使用Python定时清理运行超时的pdflatex僵尸进程
  9. 洛谷 P5048 - [Ynoi2019 模拟赛] Yuno loves sqrt technology III(分块)
  10. wget 命令用法