Java 介面程式設計題
阿新 • • 發佈:2020-12-28
應用場景舉例:
當不同身份的使用者請求一個介面時,用來校驗使用者某些身份,這樣可以對單個欄位資料進行精確許可權控制,具體看程式碼註釋
自定義註解
/** * 對比請求的使用者身份是否符合 * @author liuyalong * @date 2020/9/25 16:03 */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface CompareUser { /** * The name of the request parameter to bind . */ @AliasFor("name") String value() default ""; @AliasFor("value") String name() default ""; }
給controller的欄位添加註解
@ApiOperation(value = "刪除使用者",notes = "根據手機號來刪除使用者") @PostMapping(value = "/delete_phone") public BaseCommonResult<Integer> deletePhone(@CompareUser(value = "phone") String phone) { int i = userService.deleteByPhone(phone); return BaseCommonResult.success(i); }
引數解析器
記得繼承後加@Component,這裡是Base...所以不用
/** * @author liuyalong * @date 2020/9/25 15:56 */ public class BaseCurrentUserInterceptor implements HandlerMethodArgumentResolver { /** * 用於判定是否需要處理該引數註解,返回true為需要, * 並會去呼叫下面的方法resolveArgument。 */ @Override public boolean supportsParameter(MethodParameter parameter) { //只處理CurrentUser註解修飾的引數 return parameter.hasParameterAnnotation(CompareUser.class); } /** * 對比使用者資訊 */ @Override public Object resolveArgument(MethodParameter parameter,ModelAndViewContainer mavContainer,NativeWebRequest webRequest,WebDataBinderFactory binderFactory) throws Exception { CompareUser parameterAnnotation = parameter.getParameterAnnotation(CompareUser.class); Class<?> parameterType = parameter.getParameterType(); if (parameterAnnotation == null) { throw new IllegalArgumentException("Unknown parameter type [" + parameterType.getName() + "]"); } /* * 獲取要驗證的欄位名 */ //檢查是否給欄位取了別名 String paramName = "".equalsIgnoreCase(parameterAnnotation.name()) ? parameterAnnotation.value() : parameterAnnotation.name(); if ("".equalsIgnoreCase(parameterAnnotation.name())) { //從引數中獲取定義的欄位名 paramName = parameter.getParameter().getName(); } //獲取請求欄位的值 String paramValue = String.valueOf(webRequest.getParameter(paramName)); //從請求頭中獲取已經登入的使用者 String userName = webRequest.getHeader(AuthConstant.USER_TOKEN_HEADER); //對於root使用者,可以操作一切,所以直接返回 if (!AuthConstant.ROOT_USER.equals(userName)) { //判斷身份是否一致,不一致就丟擲異常,讓RestControllerAdvice處理 if (userName == null || !userName.equals(paramValue)) { throw new NotSameAuthorException(); } } //將引數原封不動返回出去,需要還原回需要的型別 WebDataBinder binder = binderFactory.createBinder(webRequest,parameterType,paramName); return binder.convertIfNecessary(paramValue,parameter); } }
配置WebMvcConfigurer
注意這裡提供了兩種方式載入,因為
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private HandlerInterceptor handlerInterceptor; @Autowired private HandlerMethodArgumentResolver currentUserInterceptor; @Autowired private RequestMappingHandlerAdapter requestMappingHandlerAdapter; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(handlerInterceptor).addPathPatterns("/**"); } //引數解析器,自定義的優先順序最低,所以會失效,// 解決方案是下面的 @PostConstruct,把優先順序調最高 // 但是這樣@PathParam @RequestParam就失效了,@CompareUser(value="xxx")可以完全替換@RequestParam功能 // @Override // public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { // resolvers.add(currentUserInterceptor); // // } /** *引數解析器優先順序調最高 */ @PostConstruct public void init() { // 獲取當前 RequestMappingHandlerAdapter 所有的 Resolver 物件 List<HandlerMethodArgumentResolver> resolvers = requestMappingHandlerAdapter.getArgumentResolvers(); List<HandlerMethodArgumentResolver> newResolvers = new ArrayList<>(resolvers.size() + 1); // 新增自定義引數解析器到集合首位 newResolvers.add(currentUserInterceptor); // 新增 已註冊的 Resolver 物件集合 newResolvers.addAll(resolvers); // 重新設定 Resolver 物件集合 requestMappingHandlerAdapter.setArgumentResolvers(newResolvers); } }
效果
只有特定身份人員才可以刪除操作
以上就是SpringBoot 攔截器和自定義註解判斷請求是否合法的詳細內容,更多關於SpringBoot 攔截器和自定義註解的資料請關注我們其它相關文章!