Several ways to realize general auth authentication in spring boot
Program description DD 2021-06-25 01:52:33

The article introduces spring-boot To achieve universal auth Four ways of , Include Tradition AOP、 Interceptor 、 Parameter parsers and filters , And provide the corresponding instance code , In the end, it summarizes their execution sequence .

Preface

Recently, it has been inundated by endless business demands , No time to breathe , I finally got a job that allowed me to break through the code comfort zone , The process of solving it is very tortuous , Once let me doubt life , But the harvest is also great , The code aspect is not obvious , But I feel like I've erased java、Tomcat、Spring A layer of yarn that has been blocking my eyes . Their understanding has reached a new level .

It's been a long time , So pick one aspect to summarize , I hope to know something else in the process of carding . because Java Prosperous Ecology , Each of the following modules has a large number of articles dedicated to . So I chose another angle , Starting from the practical problems , Connect these scattered pieces of knowledge , You can look at it as a summary . Detailed introduction of each module , You can go to official documents or other blogs on the Internet .

The requirements are simple and clear , It's not the same as the demand of the products : In our web Add a Universal Of appkey White list verification function , I hope it's more scalable .

This web The framework is based on spring-boot Realized , Between business and Spring Between frames , Do some business oriented general functions , Such as Log output 、 Function switch 、 General parameter analysis, etc . It's usually transparent to the business , I've been busy getting the needs right recently , Code well , Never even noticed it .

Tradition AOP

For this need , The first thing to think of, of course, is Spring-boot Provided AOP Interface , Only need Controller Method , Then the tangent point can be processed .

Realization

The steps are as follows :

  1. Use @Aspect Declare the aspect class WhitelistAspect;

  2. Add a pointcut to the facet class whitelistPointcut(), In order to achieve this tangent point flexible assembly ability , Not used here execution Intercept all , Instead, add an annotation @Whitelist, The annotated method will verify the whitelist .

  3. Use... In section classes spring Of AOP annotation @Before Declare a notification method checkWhitelist() stay Controller Verify whitelist before method is executed .

The pseudo code of aspect class is as follows

 @Aspect
public class WhitelistAspect {

@Before(value = "whitelistPointcut() && @annotation(whitelist)")
public void checkAppkeyWhitelist(JoinPoint joinPoint, Whitelist whitelist) {
checkWhitelist();
// You can use joinPoint.getArgs() obtain Controller Method parameters
// have access to whitelist Variables get annotation parameters
}


@Pointcut("@annotation(com.zhenbianshu.Whitelist)")
public void whitelistPointCut() {
}
}
  1. stay Controller Method @Whitelist Annotations implement functions .

Expand

In this example, you used annotation To declare the tangent point , And I have realized to declare the whitelist to be verified through annotation parameters , If you need to add another white list later , Such as through UID To verify , You can add uid() Other methods , Implement custom verification .

Besides ,spring Of AOP And support execution( Execution method ) 、bean( That matches a specific name Bean Object execution method ) Equitangent point declaration method and @Around( In the execution of the objective function ) 、@After( After method execution ) And so on .

such , The function has been realized , But the leaders are not satisfied =_=, The reason is that in the project AOP Too much , It's overused , Suggest that I do it another way . Um. , We have to start .

Interceptor

Spring Of Interceptor (Interceptor) It's also very appropriate to implement this function . seeing the name of a thing one thinks of its function , Interceptors are used in Controller Inside Action Before being executed, judge whether to execute this method through some parameters , To implement an interceptor , Can achieve Spring Of HandlerInterceptor Interface .

Realization

The implementation steps are as follows :

  1. Define the interceptor class AppkeyInterceptor Class and Implementation HandlerInterceptor Interface .
  2. To achieve its preHandle() Method ;
  3. stay preHandle In the method, we use annotations and parameters to determine whether the request needs to be intercepted , When intercepting a request, the interface returns false;
  4. In the custom WebMvcConfigurerAdapter Register this interceptor in class ;

AppkeyInterceptor The categories are as follows :

@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(); adopt request Get request parameters , adopt whitelist Variables get annotation parameters
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// Method in Controller Execute after method execution
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// stay view After the view rendering, execute
}
}

Expand

To enable the The interceptor also explicitly configures it to enable , Here we use WebMvcConfigurerAdapter Configure it . We need to pay attention to , To inherit it MvcConfiguration Need to be in ComponentScan Under the path .

@Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new WhitelistInterceptor()).addPathPatterns("/*").order(1);
// Here you can configure the interceptor enabled path The order of , When there are multiple interceptors , Any interceptor returns false Will make the subsequent request method no longer execute
}
}

Attention is also needed , After successful execution of interceptor, the response code is 200, But the response data is empty .

When the interceptor is used to realize the function , The leader finally made a big move : We already have one Auth Parameters ,appkey It can be downloaded from Auth The parameter takes , You can take being on the white list as Auth One way , Why not Auth Time verification ?emmm… Vomiting blood .

ArgumentResolver

The parameter resolver is Spring Provides tools for parsing custom parameters , That we use a lot @RequestParam Annotation has its shadow , Use it , We can put the parameters into Controller Action It's been put together as we want it to be .Spring Will maintain a ResolverList, When the request arrives ,Spring Found a custom type parameter ( Non basic type ), I'll try these in turn Resolver, Until there is one Resolver Can parse the required parameters . To implement a parameter parser , Need to achieve HandlerMethodArgumentResolver Interface .

Realization

  1. Define custom parameter types AuthParam, In class appkey Related fields ;
  2. Definition AuthParamResolver And implement HandlerMethodArgumentResolver Interface ;
  3. Realization supportsParameter() The interface method will AuthParam And AuthParamResolver Fit up ;
  4. Realization resolveArgument() Interface method parsing reqest Object to generate AuthParam object , And check here AuthParam , confirm appkey Is it on the white list ;
  5. stay Controller Action Method to add AuthParam Parameter to enable this Resolver;

Realized AuthParamResolver The categories are as follows :

@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);
// adopt webRequest and whitelist Verify whitelist
return new AuthParam();
}
}

Expand

Of course , Using the parameter parser also requires a separate configuration , We are also in WebMvcConfigurerAdapter Internal configuration :

@Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter {

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new AuthParamResolver());
}
}

It's done this time , I'm still a little worried , So find out whether there are other ways to achieve this function on the Internet , It's also found that Filter.

Filter

Filter Not at all Spring Provided , It's in Servlet As defined in the specification , yes Servlet The container supports . By Filter Filtered requests , It won't be distributed to Spring In the container . It is also relatively simple to implement , Realization javax.servlet.Filter Interface can .

Because I'm not in Spring In the container ,Filter Can't get Spring The resources of the container , Only use native Java Of ServletRequest and ServletResponse To get the request parameters .

in addition , In a Filter To display the call FilterChain Of doFilter Method , Otherwise, the request will be intercepted . The implementation is similar to :

public class WhitelistFilter implements javax.servlet.Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Called once after initialization
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// Decide if you need to intercept
chain.doFilter(request, response); // Request through to show call
}

@Override
public void destroy() {
// Called once when destroyed
}
}

Expand

Filter Also need to display configuration :

@Configuration
public class FilterConfiguration {

@Bean
public FilterRegistrationBean someFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new WhitelistFilter());
registration.addUrlPatterns("/*");
registration.setName("whitelistFilter");
registration.setOrder(1); // Set the order in which filters are called
return registration;
}
}

Summary

The four implementations all have their own suitable scenarios , So what's the call order between them ?

Filter yes Servlet Realized , Nature is the first to be called , What's called next is Interceptor If it is intercepted, there is no need to deal with it later , And then there was Parameter resolver , The last is The tangent point of the section . I will implement all four methods in one project , The output log also proves this conclusion .

The author of this article :zhenbianshu,
Link to the original text :https://zhenbianshu.github.io/
The copyright belongs to the author , Please indicate the author of the reprint 、 original text 、 Translators and other source information
Please bring the original link to reprint ,thank
Similar articles