版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
springboot过滤字段_SpringBoot使⽤过滤器和拦截器分别实现REST接⼝简。。。本⽂通过⼀个简易安全认证⽰例的开发实践,理解过滤器和拦截器的⼯作原理。很多⽂章都将过滤器(Filter)、拦截器(Interceptor)和监听器(Listener)这三者和Spring关联起来讲解,并认为过滤器(Filter)、拦截器(Interceptor)和监听器(Listener)是Spring提供的应⽤⼴泛的组件功能。但是严格来说,过滤器和监听器属于Servlet范畴的API,和Spring没什么关系。因为过滤器继承⾃javax.servlet.Filter接⼝,监听器继承⾃javax.servlet.ServletContextListener接⼝,只有拦截器继承的是org.springframework.web.servlet.HandlerInterceptor接⼝。上⾯的流程图参考⾃⽹上资料,⼀图胜千⾔。看完本⽂以后,将对过滤器和拦截器的调⽤过程会有更深刻理解。⼀、安全认证设计思路有时候内外⽹调⽤API,对安全性的要求不⼀样,很多情况下外⽹调⽤API的种种限制在内⽹根本没有必要,但是⽹关部署的时候,可能因为成本和复杂度等问题,内外⽹要调⽤的API会部署在⼀起。实现REST接⼝的安全性,可以通过成熟框架如SpringSecurity或者shiro搞定。但是因为安全框架往往实现复杂(我数了下SpringSecurity,洋洋⼤概有11个⼼模块,shiro的源码代码量也⽐较惊⼈)同时可能要引⼊复杂配置(能不能让⼈痛快⼀点),不利于中⼩团队的灵活快速开发、部署及问题排查。很多团队⾃⼰造轮⼦实现安全认证,本⽂这个简易认证⽰例参考⾃我所的前⼚开发团队,可以认为是个基于token的安全认证服务。⼤致设计思路如下:1、⾃定义http请求头,每次调⽤API都请求头⾥传⼈⼀个token值2、token放在缓存(如redis)中,根据业务和API的不同设置不同策略的过期时间3、token可以设置⽩名单和⿊名单,可以限制API调⽤频率,便于开发和测试,便于紧急处理异状,甚⾄临时关闭API4、外⽹调⽤须传⼈token,token可以和⽤户有关系,⽐如每次打开页⾯或者登录⽣成token写⼊请求头,页⾯验证cookie和token有效性等在SpringSecurity⾥有两个概念,即认证和授权,认证指可以访问系统的⽤户,⽽授权则是⽤户可以访问的资源。实现上述简易安全认证需求,你可能需要独⽴出⼀个token服务,保证⽣成token全局唯⼀,可能包含的模块有⾃义流⽔⽣成器、CRM、加解密、⽇志、API统计、缓存等,但是和⽤户(CRM)其实是弱绑定关系。某些和⽤户有关系的公共服务,⽐如我们经常⽤到的发送短信SMS和邮件服务,也可以通过token机制解决安全调⽤问题。综上,本⽂的简易安全认证其实和SpringSecurity框架提供的认证和授权有点不⼀样,当然,这种“安全”处理⽅式对专业⼈⼠没什么新意,但是可以对外挡掉很⼤⼀分⼩⽩⽤户。⼆、⾃定义Filter和SpringMVC类似,SpringBoot提供了很多servlet过滤器(Filter)可使⽤,并且它⾃动添加了⼀些常⽤过滤器,⽐如CharacterEncodingFilter(⽤于处理编码问题)、HiddenHttpMethodFilter(隐藏HTTP函数)、HttpPutFormContentFilter(form表单处理)、RequestContextFilter(请求上下⽂)等。通常我们还会⾃定义Filter实现⼀些通⽤功能,⽐记录⽇志、判断是否登录、权限验证等。1、⾃定义请求头很简单,r在equestheader添加⾃定义请求头authtoken:@RequestMapping(value="/getinfobyid",method=RequestMethod.POST)@ApiOperation("根据商品Id查询商品信息")@ApiImplicitParams({
@ApiImplicitParam(paramType="header",name="authtoken",required=true,value="authtoken",dataType="String"),})publicGetGoodsByGoodsIdResponsegetGoodsByGoodsId(@RequestHeaderStringauthtoken,@RequestBodyGetGoodsByGoodsIdRequestrequest){return_goodsApiService.getGoodsByGoodsId(request);}getGoodsByGoodsId加了@RequestHeader修饰的authtoken字段就可以在swagger这样的框架下显⽰出来。调⽤后,可以根据http⼯具看到请求头,本⽂⽰例是authtoken(和某些框架的token区分开):备注:很多httpclient⼯具都⽀持动态传⼈请求头,⽐如RestTemplate。2、实现FilterFilter接⼝共有三个⽅法,即init,doFilter和destory,看到名称就⼤概知道它们主要⽤途了,通常我们只要在doFilter这个⽅法内,对Http请求进⾏处理:packagecom.power.demo.controller.filter;importmon.AppConst;importmon.BizResult;importcom.power.demo.service.contract.AuthTokenService;importcom.power.demo.util.PowerLogger;importcom.power.demo.util.SerializeUtil;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importjavax.servlet.*;importjavax.servlet.http.HttpServletRequest;importjava.io.IOException;@ComponentpublicclassAuthTokenFilterimplementsFilter{@AutowiredprivateAuthTokenServiceauthTokenService;@Overridepublicvoidinit(FilterConfigvar1)throwsServletException{}@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)
throwsIOException,ServletException{HttpServletRequestreq=(HttpServletRequest)request;Stringtoken=req.getHeader(AppConst.AUTH_TOKEN);BizResultbizResult=authTokenService.powerCheck(token);System.out.println(SerializeUtil.Serialize(bizResult));if(bizResult.getIsOK()==true){PowerL("authtokenfilterpassed");chain.doFilter(request,response);}else{thrownewServletException(bizResult.getMessage());}}@Overridepublicvoiddestroy(){}}AuthTokenFilter注意,Filter这样的东西,我认为从实际分层⾓度,多数处理的还是表现层偏多,不建议直接在Filter中直接使⽤数据访问层Dao,虽然这样的代码⼀两年前我在很多⽼古董项⽬中看到过很多次,⽽且<>的书⾥也有这样写的先例。3、认证服务这⾥就是主要业务逻辑了,⽰例代码只是简单写下思路,不要轻易就⽤于⽣产环境:packagecom.power.demo.service.impl;importcom.power.demo.cache.PowerCacheBuilder;importmon.BizResult;importcom.power.demo.service.contract.AuthTokenService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importorg.springframework.util.StringUtils;@ComponentpublicclassAuthTokenServiceImplimplementsAuthTokenService{@AutowiredprivatePowerCacheBuildercacheBuilder;/**验证请求头token是否合法
**/@OverridepublicBizResultpowerCheck(Stringtoken){BizResultbizResult=newBizResult<>(true,"验证通过");System.out.println("token的值为:"+token);if(StringUtils.isEmpty(token)==true){bizResult.setFail("authtoken为空");returnbizResult;}//处理⿊名单bizResult=checkForbidList(token);if(bizResult.getIsOK()==false){returnbizResult;}//处理⽩名单bizResult=checkAllowList(token);if(bizResult.getIsOK()==false){returnbizResult;}Stringkey=String.format("Power.AuthTokenService.%s",token);//cacheBuilder.set(key,token);//cacheBuilder.set(key,token.toUpperCase());//从缓存中取StringexistToken=cacheBuilder.get(key);if(StringUtils.isEmpty(existToken)==true){bizResult.setFail(String.format("不存在此authtoken:%s",token));returnbizResult;}//⽐较token是否相同BooleanisEqual=token.equals(existToken);if(isEqual==false){bizResult.setFail(String.format("不合法的authtoken:%s",token));returnbizResult;}
//dosomethingreturnbizResult;}}AuthTokenServiceImpl⽤到的缓存服务可以参考这⾥,这个也是我在前⼚的经验总结。4、注册Filter常见的有两种写法:(1)、使⽤@WebFilter注解来标识Filter@Order(1)@WebFilter(urlPatterns={"/api/v1/goods/*","/api/v1/userinfo/*"})publicclassAuthTokenFilterimplementsFilter{使⽤@WebFilter注解,还可以配合使⽤@Order注解,@Order注解表⽰执⾏过滤顺序,值越⼩,越先执⾏,这个Order⼤⼩在我们编程过程中就像处理HTTP请求的⽣命周期⼀样⼤有⽤处。当然,如果没有指定Order,则过滤器的调⽤顺序跟添加的过滤器顺序相反,过滤器的实现是责任链模式。最后,在启动类上添加@ServletComponentScan注解即可正常使⽤⾃定义过滤器了。(2)、使⽤FilterRegistrationBean对Filter进⾏⾃定义注册本⽂以第⼆种实现⾃定义Filter注册:packagecom.power.demo.controller.filter;importmon.collect.Lists;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.web.servlet.FilterRegistrationBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.stereotype.Component;importjava.util.List;@Configuration@ComponentpublicclassRestFilterConfig{@AutowiredprivateAuthTokenFilterfilter;@BeanpublicFilterRegistrationBeanfilterRegistrationBean(){FilterRegistrationBeanregistrationBean=newFilterRegistrationBean();registrationBean.setFilter(filter);
//设置(模糊)匹配的urlListurlPatterns=Lists.newArrayList();urlPatterns.add("/api/v1/goods/*");urlPatterns.add("/api/v1/userinfo/*");registrationBean.setUrlPatterns(urlPatterns);registrationBean.setOrder(1);registrationBean.setEnabled(true);returnregistrationBean;}}RestFilterConfig请⼤家特别注意urlPatterns,属性urlPatterns指定要过滤的URL模式。对于Filter的作⽤区域,这个参数居功⾄伟。注册好Filter,当SpringBoot启动时监测到有javax.servlet.Filter的bean时就会⾃动加⼊过滤器调⽤链ApplicationFilterChain。调⽤⼀个API试试效果:通常情况下,我们在SpringBoot下都会⾃定义⼀个全局统⼀的异常管理增强GlobalExceptionHandler(和上⾯这个显⽰会略有不同)。根据我的实践,过滤器⾥抛出异常,不会被全局唯⼀的异常管理增强捕获到并进⾏处理,这个和拦截器Inteceptor以及下⼀篇⽂章介绍的⾃定义AOP拦截不同。到这⾥,⼀个通过⾃定义Filter实现的简易安全认证服务就搞定了。三、⾃定义拦截器1、实现拦截器继承接⼝HandlerInterceptor,实现拦截器,接⼝⽅法有下⾯三个:preHandle是请求执⾏前执⾏postHandle是请求结束执⾏afterCompletion是视图渲染完成后执⾏packageerceptor;importmon.AppConst;importmon.BizResult;importcom.power.demo.service.contract.AuthTokenService;importcom.power.demo.util.PowerLogger;importcom.power.demo.util.SerializeUtil;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importorg.springframework.web.servlet.HandlerInterceptor;importorg.springframework.web.servlet.ModelAndView;
importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;/**认证token拦截器**/@ComponentpublicclassAuthTokenInterceptorimplementsHandlerInterceptor{@AutowiredprivateAuthTokenServiceauthTokenService;/**请求执⾏前执⾏**/@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{booleanhandleResult=false;Stringtoken=request.getHeader(AppConst.AUTH_TOKEN);BizResultbizResult=authTokenService.powerCheck(token);System.out.println(SerializeUtil.Serialize(bizResult));handleResult=bizResult.getIsOK();PowerL("authtokeninterceptor拦截结果:"+handleResult);if(bizResult.getIsOK()==true){PowerL("authtokeninterceptorpassed");}else{thrownewException(bizResult.getMessage());}returnhandleResult;}/**请求结束执⾏**/@OverridepublicvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView)throwsException{}
/**视图渲染完成后执⾏**/@OverridepublicvoidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Exceptionex)throwsException{}}AuthTokenInterceptor⽰例中,我们选择在请求执⾏前进⾏token安全认证。认证服务就是过滤器⾥介绍的AuthTokenService,业务逻辑层实现复⽤。2、注册拦截器定义⼀个InterceptorConfig类,继承⾃WebMvcConfigurationSupport,WebMvcConfigurerAdapter已经过时。将AuthTokenInterceptor作为bean注⼊,其他设置拦截器拦截的URL和过滤器⾮常相似:packageerceptor;importmon.collect.Lists;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.stereotype.Component;importorg.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;importjava.util.List;@Configuration@ComponentpublicclassInterceptorConfigextendsWebMvcConfigurationSupport{//WebMvcConfigurerAdapter已经过时privatestaticfinalStringFAVICON_URL="/favicon.ico";/***发现如果继承了WebMvcConfigurationSupport,则在yml中配置的相关内容会失效。**@paramregistry*/@Override
publicvoidaddResourceHandlers(ResourceHandlerRegistryregistry){registry.addResourceHandler("/").addResourceLocations("/**");registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");}/***配置servlet处理*/@OverridepublicvoidconfigureDefaultServletHandling(DefaultServletHandlerConfigurerconfigurer){configurer.enable();}@OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){//设置(模糊)匹配的urlListurlPatterns=Lists.newArrayList();urlPatterns.add("/api/v1/goods/*");urlPatterns.add("/api/v1/userinfo/*");registry.addInterceptor(authTokenInterceptor()).addPathPatterns(urlPatterns).excludePathPatterns(FAVICON_URL);super.addInterceptors(registry);}//将拦截器作为bean写⼊配置中@BeanpublicAuthTokenInterceptorauthTokenInterceptor(){returnnewAuth
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 发型师卷棒造型培训
- 2024年项目融资合同详细条款与标的说明
- 2024年经营权承包详细规定协议版B版
- 甲状腺切除手术后护理
- 压疮的诱因及预防护理
- 2025年度中英文版临时工聘用及福利待遇协议3篇
- 二零二五年度全款交易二手房买卖合同范本3篇
- 2025年度合肥市租赁房屋租赁合同纠纷调解服务合同3篇
- 2024年货物进出口赔偿协议
- 2024年食品配送安全协议
- 养猪场施工噪声环境影响分析
- Windows-Server-2012网络服务架构课件(完整版)
- 2022版义务教育语文课程标准(2022版含新增和修订部分)
- 形位公差_很详细(基础教育)
- 手榴弹使用教案
- 600MW机组除氧器水位控制系统
- 史上最全的涉税风险
- 初中数学问题情境的创设
- 朱东润《中国历代文学作品选》目录简体字版
- 电力设备典型消防规程.ppt
- 北京兴昌达博房地产开发有限公司重整计划
评论
0/150
提交评论