SpringBoot 項(xiàng)目鑒權(quán)的 4 種方式
點(diǎn)擊上方“碼農(nóng)突圍”,馬上關(guān)注
這里是碼農(nóng)充電第一站,回復(fù)“666”,獲取一份專屬大禮包
真愛,請?jiān)O(shè)置“星標(biāo)”或點(diǎn)個(gè)“在看”

前言
通用的 appkey 白名單校驗(yàn)功能,希望它的擴(kuò)展性更好一些。傳統(tǒng)AOP
實(shí)現(xiàn)
使用?
@Aspect?聲明一下切面類?WhitelistAspect;在切面類內(nèi)添加一個(gè)切點(diǎn)?
whitelistPointcut(),為了實(shí)現(xiàn)此切點(diǎn)靈活可裝配的能力,這里不使用?execution?全部攔截,而是添加一個(gè)注解?@Whitelist,被注解的方法才會(huì)校驗(yàn)白名單。在切面類中使用 spring 的 AOP 注解?
@Before?聲明一個(gè)通知方法?checkWhitelist()?在 Controller 方法被執(zhí)行之前校驗(yàn)白名單。
@Aspect??
public?class?WhitelistAspect?{??
?????
?@Before(value?=?"whitelistPointcut()?&&?@annotation(whitelist)")??
?public?void?checkAppkeyWhitelist(JoinPoint?joinPoint,?Whitelist?whitelist)?{??
?????checkWhitelist();??
?????//?可使用?joinPoint.getArgs()?獲取Controller方法的參數(shù)??
?????//?可以使用?whitelist?變量獲取注解參數(shù)??
?}??
?????
?????
?@Pointcut("@annotation(com.zhenbianshu.Whitelist)")??
?public?void?whitelistPointCut()?{??
?}??
}??
@Whitelist?注解實(shí)現(xiàn)功能。擴(kuò)展
uid()?等方法,實(shí)現(xiàn)自定義校驗(yàn)。此外,spring 的 AOP 還支持?execution(執(zhí)行方法) 、bean(匹配特定名稱的 Bean 對象的執(zhí)行方法)等切點(diǎn)聲明方法和?@Around(在目標(biāo)函數(shù)執(zhí)行中執(zhí)行) 、@After(方法執(zhí)行后)?等通知方法。如此,功能已經(jīng)實(shí)現(xiàn)了,但領(lǐng)導(dǎo)并不滿意,原因是項(xiàng)目中 AOP 用得太多了,都用濫了,建議我換一種方式。嗯,只好搞起。Interceptor
HandlerInterceptor?接口。實(shí)現(xiàn)
定義攔截器類?
AppkeyInterceptor?類并實(shí)現(xiàn) HandlerInterceptor 接口。實(shí)現(xiàn)其?
preHandle()?方法;在 preHandle 方法內(nèi)通過注解和參數(shù)判斷是否需要攔截請求,攔截請求時(shí)接口返回?
false;在自定義的?
WebMvcConfigurerAdapter?類內(nèi)注冊此攔截器;
AppkeyInterceptor?類如下:@Component??
public?class?WhitelistInterceptor?implements?HandlerInterceptor?{??
??
????@Override??
????public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{??
????????Whitelist?whitelist?=?((HandlerMethod)?handler).getMethodAnnotation(Whitelist.class);??
????????//?whitelist.values();?通過?request?獲取請求參數(shù),通過?whitelist?變量獲取注解參數(shù)??
????????return?true;??
????}??
??
????@Override??
????public?void?postHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?ModelAndView?modelAndView)?throws?Exception?{??
??//?方法在Controller方法執(zhí)行結(jié)束后執(zhí)行??
????}??
??
????@Override??
????public?void?afterCompletion(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?Exception?ex)?throws?Exception?{??
??//?在view視圖渲染完成后執(zhí)行??
????}??
}??
擴(kuò)展
WebMvcConfigurerAdapter?對它進(jìn)行配置。需要注意,繼承它的的?MvcConfiguration?需要在?ComponentScan?路徑下。@Configuration??
public?class?MvcConfiguration?extends?WebMvcConfigurerAdapter?{??
????@Override??
????public?void?addInterceptors(InterceptorRegistry?registry)?{??
????????registry.addInterceptor(new?WhitelistInterceptor()).addPathPatterns("/*").order(1);??
????????//?這里可以配置攔截器啟用的?path?的順序,在有多個(gè)攔截器存在時(shí),任一攔截器返回?false?都會(huì)使后續(xù)的請求方法不再執(zhí)行??
????}??
}??
200,但響應(yīng)數(shù)據(jù)為空。ArgumentResolver
@RequestParam?注解就有它的影子,使用它,我們可以將參數(shù)在進(jìn)入Controller Action之前就組合成我們想要的樣子。ResolverList, 在請求到達(dá)時(shí),Spring 發(fā)現(xiàn)有自定義類型參數(shù)(非基本類型), 會(huì)依次嘗試這些 Resolver,直到有一個(gè) Resolver 能解析需要的參數(shù)。要實(shí)現(xiàn)一個(gè)參數(shù)解析器,需要實(shí)現(xiàn)?HandlerMethodArgumentResolver?接口。實(shí)現(xiàn)
定義自定義參數(shù)類型?
AuthParam,類內(nèi)有 appkey 相關(guān)字段;定義?
AuthParamResolver?并實(shí)現(xiàn) HandlerMethodArgumentResolver 接口;實(shí)現(xiàn)?
supportsParameter()?接口方法將 AuthParam 與 AuthParamResolver 適配起來;實(shí)現(xiàn)?
resolveArgument()?接口方法解析 reqest 對象生成 AuthParam 對象,并在此校驗(yàn) AuthParam ,確認(rèn) appkey 是否在白名單內(nèi);在 Controller Action 方法上簽名內(nèi)添加 AuthParam 參數(shù)以啟用此 Resolver;
AuthParamResolver?類如下:@Component??
public?class?AuthParamResolver?implements?HandlerMethodArgumentResolver?{??
??
????@Override??
????public?boolean?supportsParameter(MethodParameter?parameter)?{??
????????return?parameter.getParameterType().equals(AuthParam.class);??
????}??
??
????@Override??
????public?Object?resolveArgument(MethodParameter?parameter,?ModelAndViewContainer?mavContainer,?NativeWebRequest?webRequest,?WebDataBinderFactory?binderFactory)?throws?Exception?{??
????????Whitelist?whitelist?=?parameter.getMethodAnnotation(Whitelist.class);??
????????//?通過?webRequest?和?whitelist?校驗(yàn)白名單??
????????return?new?AuthParam();??
????}??
}??
擴(kuò)展
WebMvcConfigurerAdapter內(nèi)配置:@Configuration??
public?class?MvcConfiguration?extends?WebMvcConfigurerAdapter?{??
??
????@Override??
????public?void?addArgumentResolvers(List?argumentResolvers) ?{??
????????argumentResolvers.add(new?AuthParamResolver());??
????}??
}??
Filter。Filter
javax.servlet.Filter接口即可。public?class?WhitelistFilter?implements?javax.servlet.Filter?{??
??
????@Override??
????public?void?init(FilterConfig?filterConfig)?throws?ServletException?{??
??//?初始化后被調(diào)用一次??
????}??
??
????@Override??
????public?void?doFilter(ServletRequest?request,?ServletResponse?response,?FilterChain?chain)?throws?IOException,?ServletException?{??
?????//?判斷是否需要攔截??
???????chain.doFilter(request,?response);?//?請求通過要顯示調(diào)用??
????}??
??
????@Override??
????public?void?destroy()?{??
?????//?被銷毀時(shí)調(diào)用一次??
????}??
}??
擴(kuò)展
@Configuration??
public?class?FilterConfiguration?{??
??
????@Bean??
????public?FilterRegistrationBean?someFilterRegistration()?{??
????????FilterRegistrationBean?registration?=?new?FilterRegistrationBean();??
????????registration.setFilter(new?WhitelistFilter());??
????????registration.addUrlPatterns("/*");??
????????registration.setName("whitelistFilter");??
????????registration.setOrder(1);?//?設(shè)置過濾器被調(diào)用的順序??
????????return?registration;??
????}??
}??
小結(jié)
來源:https://zhenbianshu.github.io
(完)
碼農(nóng)突圍資料鏈接
1、臥槽!字節(jié)跳動(dòng)《算法中文手冊》火了,完整版 PDF 開放下載!
2、計(jì)算機(jī)基礎(chǔ)知識(shí)總結(jié)與操作系統(tǒng) PDF 下載
3、艾瑪,終于來了!《LeetCode Java版題解》.PDF
4、Github 10K+,《LeetCode刷題C/C++版答案》出爐.PDF歡迎添加魚哥個(gè)人微信:smartfish2020,進(jìn)粉絲群或圍觀朋友圈
