この要件について、最初に思い浮かぶのは、もちろん Spring-boot によって提供される AOP インターフェイスです。必要なのは、Controller メソッドの前にポイントカットを追加してから、ポイントカット。
手順は次のとおりです:
@Aspect を使用してアスペクト クラス WhitelistAspect を宣言します;
アスペクト クラスにポイントカットwhitelistPointcut()を追加します。このポイントカットの柔軟でアセンブリ可能な機能を実現するために、実行を使用してすべてをインターセプトするのではなく、アノテーション @Whitelist を追加します。 、注釈付きのメソッドはホワイトリストがチェックされます。
アスペクト クラスで Spring の AOP アノテーション @Before を使用して通知メソッド checkWhitelist() を宣言し、Controller メソッドが実行される前にホワイトリストを検証します。
アスペクト クラスの疑似コードは次のとおりです。
@Aspect public class WhitelistAspect { @Before(value = "whitelistPointcut() && @annotation(whitelist)") public void checkAppkeyWhitelist(JoinPoint joinPoint, Whitelist whitelist) { checkWhitelist(); // 可使用 joinPoint.getArgs() 获取Controller方法的参数 // 可以使用 whitelist 变量获取注解参数 } @Pointcut("@annotation(com.zhenbianshu.Whitelist)") public void whitelistPointCut() { } }
Controller メソッドに @Whitelist アノテーションを追加して機能を実装します。
この例では、アノテーションはポイントカットの宣言に使用されており、検証されるホワイトリストを宣言するためにアノテーション パラメーターを実装しました。後で他のホワイトリストを追加する必要がある場合は、リストが UID によって検証される場合、このアノテーションに uid() などのメソッドを追加してカスタム検証を実装できます。
さらに、Spring の AOP では、execution (実行メソッド)、Bean (特定の名前に一致する Bean オブジェクトの実行メソッド)、@Around (ターゲットの実行時に実行される) などのポイントカット宣言メソッドもサポートされています。 function) 、 @After (メソッド実行後) およびその他の通知メソッド。
つまり、機能は実装されましたが、リーダーは満足していません =_=。その理由は、プロジェクトで AOP が多用されすぎているためです。彼は、方法を変更することを提案しました。 。まあ、始めるしかなかった。こちらにも注目:馬源技術コラム、背景にある回答:大手インターネット企業の面接質問集の最新版高精細PDF 3625ページ「面接ガイド」を入手できます。
Spring の Interceptor も、この関数の実装に非常に適しています。名前が示すように、インターセプターは、コントローラーのアクションが実行される前に、いくつかのパラメーターを通じてこのメソッドを実行するかどうかを決定するために使用されます。インターセプターを実装するには、Spring の HandlerInterceptor インターフェイスを実装できます。
実装手順は次のとおりです。
インターセプタ クラス AppkeyInterceptor クラスを定義し、HandlerInterceptor インターフェイスを実装します。
preHandle() メソッドを実装します;
preHandle メソッドの注釈とパラメータを使用して、リクエストをインターセプトする必要があるかどうかを判断します。リクエストをインターセプトすると、インターフェイスは false を返します。
#このインターセプターをカスタム WebMvcConfigurerAdapter クラスに登録します。
#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 获取请求参数,通过 whitelist 变量获取注解参数 return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 方法在Controller方法执行结束后执行 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 在view视图渲染完成后执行 } }
インターセプターを有効にするには、明示的に構成する必要もあります。ここでは、WebMvcConfigurerAdapter を使用して構成します。それを継承する MvcConfiguration が ComponentScan パス内にある必要があることに注意してください。
@Configuration public class MvcConfiguration extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new WhitelistInterceptor()).addPathPatterns("/*").order(1); // 这里可以配置拦截器启用的 path 的顺序,在有多个拦截器存在时,任一拦截器返回 false 都会使后续的请求方法不再执行 } }
また、インターセプターが正常に実行された後の応答コードは 200 ですが、応答データは空であることに注意してください。
インターセプターを使用して関数を実装した後、リーダーはついに大きな手を思いつきました。すでに Auth パラメーターがあり、Appkey は Auth パラメーターから取得でき、ホワイトリストの有無を使用できます。認証の方法として使用されています。なぜですか? 認証中に検証が行われないのですか?うーん…吐血。
パラメータ パーサーは、カスタム パラメータを解析するために Spring によって提供されるツールです。一般的に使用される @RequestParam アノテーションには影があります。これを使用すると、パラメータは次のように結合されます。コントローラーアクションに入る前に必要なもの。 Spring は ResolverList を維持します。リクエストが到着すると、Spring はカスタム型パラメータ (非基本型) があることを検出し、リゾルバが必要なパラメータを解析できるまでこれらのリゾルバを順番に試します。パラメーター リゾルバーを実装するには、HandlerMethodArgumentResolver インターフェイスを実装する必要があります。
カスタム パラメータ タイプ AuthParam を定義します。クラスには appkey 関連フィールドがあります。
定義AuthParamResolver そして、HandlerMethodArgumentResolver インターフェイスを実装します;
AuthParam を AuthParamResolver に適応させるために、supportsParameter() インターフェイス メソッドを実装します;
resolveArgument() インターフェイスを実装します解決するメソッド reqest オブジェクトは AuthParam オブジェクトを生成し、ここで AuthParam を検証してアプリキーがホワイトリストにあるかどうかを確認します。
コントローラー アクション メソッドの署名に AuthParam パラメーターを追加します。このリゾルバーを有効にするには;
実装された 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 校验白名单 return new AuthParam(); } }
もちろん、パラメータパーサーも別途設定する必要があり、WebMvcConfigurerAdapter での設定も必要です:
@Configuration public class MvcConfiguration extends WebMvcConfigurerAdapter { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(new AuthParamResolver()); } }
今回実装が完了した後も少し不安があったので、ネットで調べてみました。この機能を実現する別の方法を検討したところ、フィルターが一般的な方法であることがわかりました。
Filter 并不是 Spring 提供的,它是在 Servlet 规范中定义的,是 Servlet 容器支持的。被 Filter 过滤的请求,不会派发到 Spring 容器中。它的实现也比较简单,实现 javax.servlet.Filter接口即可。
由于不在 Spring 容器中,Filter 获取不到 Spring 容器的资源,只能使用原生 Java 的 ServletRequest 和 ServletResponse 来获取请求参数。
另外,在一个 Filter 中要显示调用 FilterChain 的 doFilter 方法,不然认为请求被拦截。实现类似:
public class WhitelistFilter implements javax.servlet.Filter {
@Override public void init(FilterConfig filterConfig) throws ServletException { // 初始化后被调用一次 } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 判断是否需要拦截 chain.doFilter(request, response); // 请求通过要显示调用 } @Override public void destroy() { // 被销毁时调用一次 } }
Filter 也需要显示配置:
@Configuration public class FilterConfiguration { @Bean public FilterRegistrationBean someFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new WhitelistFilter()); registration.addUrlPatterns("/*"); registration.setName("whitelistFilter"); registration.setOrder(1); // 设置过滤器被调用的顺序 return registration; } }
以上がSpringboot がユニバーサル Auth 認証を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。