SpringBoot is a quick way to set up the interceptor and implement permission validation
- 2020-12-21 18:02:57
- OfStack
1. An overview of the
Interceptors are increasingly being used, especially with the popularity of slicing oriented programming. So what can interceptors usually do?
We mentioned earlier in the Agent introduction that statistical functions take time to call. This idea is exactly the same as AOP's wrap enhancement.
Generally speaking, the scenario is as follows:
Function enhancement: such as parameter checking for a function, or result filtering, etc. You can even authenticate to functions. Performance monitoring: Statistics function performance. Log dot: For example, before the user logs in to a function, dot statistics such as PV.
And so on and so forth.
2. Spring's interceptor
In both SpringMVC and SpringBoot, the interceptor has to be mentioned:
org.springframework.web.servlet.handler.HandlerInterceptorAdapter
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
// Execute before the target method executes
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
// Execute after the target method executes, but before the request returns, we can still apply the ModelAndView modified
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {}
// Executes after the request has been returned
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {}
// Used to handle asynchronous requests , when Controller A method is triggered when an asynchronous request is made in
@Override
public void afterConcurrentHandlingStarted(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {}
}
3. Implement an interceptor for verifying simple permissions
1. Customize 1 permission annotation @Auth
@Inherited
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Auth {
String user() default "";
}
Inherited: When using this custom annotation, if the annotation is on top of the class, the subclass inherits the annotation automatically. Otherwise, the subclass does not inherit the annotation. Keep in mind that annotations declared with Inherited are valid only when used on a class, not for methods, attributes, etc.
Target: Indicates where this annotation can be placed. Common places are: TYPE= on enumerations or annotations, FIELD= on fields, METHOD= on methods, PARAMETER= on function parameter lists, CONSTRUCTOR= on constructors, LOCAL_VARIABLE= on local variables, and so on.
Retention: Life cycle of this annotation. Common: SOURCE= source period; CLASS= Bytecode period (compiled); RUNTIME= runtime, which is usually used more often.
Documentd: Generate annotated documentation.
2. Add annotations to Controller's methods
After adding the annotations in step 1, add them to the method you are using, as follows.
@RestController
@EnableAutoConfiguration
public class DemoController {
@Auth(user = "admin")
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String sayHello() {
return "hello world.";
}
}
3. Implement interceptor function
Requirement: We verify the user when he /hello is accessed by URI. If it is admin, it will be released; otherwise, it will be refused, assuming that the user's identity is in the URL parameter.
Idea: So we want to validate the user before we execute sayHello(). Release if its identity is the same as that in the annotation. So we're going to do it in preHandle().
Difficulty: How do we get the @Auth annotation on the Controller method? Looking at the three parameters of PreHandle(), it seems that none of them can provide annotations in the Controller class.
In fact, the third parameter handler, 1 cases whose type is: org. springframework. web. method. HandlerMethod type, which contains information of annotation.
Why do you say that?
In SpringBoot, the default type of annotations is at the function level, while in SpringMVC the default type is at the Controller object level.
Therefore, if in SpringMVC you need to configure in ES93en-ES94en.xml:
<
bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/
>
, so that its type is HandlerMethod.
Let's take a look at the concrete implementation logic:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
if (!handler.getClass().isAssignableFrom(HandlerMethod.class)) {
System.out.println("cat cast handler to HandlerMethod.class");
return true;
}
// To obtain annotations
Auth auth = ((HandlerMethod) handler).getMethod().getAnnotation(Auth.class);
if (auth == null) {
System.out.println("cant find @Auth in this uri:" + request.getRequestURI());
return true;
}
// Take the user identity from the parameter and verify it
String admin = auth.user();
if (!admin.equals(request.getParameter("user"))) {
System.out.println("permission denied");
response.setStatus(403);
return false;
}
return true;
}
The implementation logic is really about two things: retrieving identities from parameters and comparing them to annotations.
4. Configure interceptors
So how do you make this interceptor work?
At this point, we need to configure WebMvcConfigurerAdapter
Specific implementation is as follows:
@Configuration
public class ConfigAdapter extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/hello");
}
}
Note: There are two things to note here. One is the @Configuration annotation so that the SpringBoot service can discover this configuration. The other one is a configuration match, and this is intercepting the "/hello" one. ("/**" is for all access intercepts)
4. Run
Visit http: / / 127.0.0.1:8080 / hello & # 63; user=admin and you can see the results.
Details of the code in this article: https: / / github com/hawkingfoo/springboot - interceptor