loading...
Springboot之HandlerInterceptor拦截器(二)
Published in:2022-01-31 | category: Spring
Words: 870 | Reading time: 4min | reading:

自定义注解

定义注解

根据需求其实UserId和UserMobile可以不要,不影响拦截器的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.ws.rs.NameBinding;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@NameBinding
public @interface UserAuthenticate {

/**
* 是否需要校验访问权限 默认不校验
* 这是预留给后台管理系统的,后台管理员角色不同访问权限不同。所以将这个设置为true后 拦截器做登录校验后,还可以做接口权限校验
* @return
*/
boolean permission() default false;
}

1
2
3
4
5
6
7
import java.lang.annotation.*;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UserId {
}
1
2
3
4
5
6
7
8
import java.lang.annotation.*;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UserMobile {
}

常量类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @ClassName HeaderCons
* @Description TODO
* @Author Ken.Yang
* @Date 2021/8/16 15:53
*/
public class HeaderCons {

/**
* 用户ID
*/
public static final String USER_ID = "H-User-Id";

public static final String USER_MOBILE = "H-User-Mobile";
}

拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
* @ClassName TestFiler
* @Description TODO
* @Author Ken.Yang
* @Date 2021/8/16 15:04
*/
public class TestFiler extends HandlerInterceptorAdapter {

private final Logger logger = LoggerFactory.getLogger(TestFiler.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("request请求地址path[{}] uri[{}]", request.getServletPath(), request.getRequestURI());
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
UserAuthenticate userAuthenticate = method.getAnnotation(UserAuthenticate.class);
//如果没有加注解则userAuthenticate为null
if(Objects.nonNull(userAuthenticate)) {
Long userId = getUserId(request);
//userAuthenticate.permission()取出permission判断是否需要校验权限
if (userId == null || (userAuthenticate.permission()) && !checkAuth(userId, request.getRequestURI())) {
throw new FastRuntimeException(20001, "No access");
}
}
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
super.afterCompletion(request, response, handler, ex);
}

/**
* 根据token获取用户ID
* @param request
* @return
*/
private Long getUserId(HttpServletRequest request){
//添加业务逻辑根据token获取用户UserId
request.getHeader("H-User-Token");
Long userId = 1L;
String userMobile = "1888888888";
request.setAttribute(HeaderCons.USER_ID, userId);
request.setAttribute(HeaderCons.USER_MOBILE, userMobile);
return userId;
}

/**
* 校验用户访问权限
* @param userId
* @param requestURI
* @return
*/
private boolean checkAuth(Long userId, String requestURI){
return true;
}

}

如果不需要使用UserId和UserMobile这两个注解到这里已经结束了。不过为了方便业务层的使用直接获取用户的id、mobile等信息我这里就加上了。

添加如下类即可取出我们在拦截器中set进去的值

1
2
3
4
5
6
7
8
9
10
11
12
13
public class UserIdMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasMethodAnnotation(UserId.class);
}

@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
return request.getAttribute(HeaderCons.USER_ID);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserMobileMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(UserMobile.class);
}

@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
HttpServletRequest servletRequest = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
return servletRequest.getAttribute(HeaderCons.USER_MOBILE);
}


}

以上类是根据你定义的注解来建设的取出放在request里面的值,如果有多个就再加就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

import com.kenyang.annotation.UserId;
import com.kenyang.annotation.UserMobile;
import com.kenyang.resolvers.UserIdMethodArgumentResolver;
import com.kenyang.resolvers.UserMobileMethodArgumentResolver;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.util.List;


/**
* @ClassName FilerAutoConfiguration
* @Description TODO
* @Author Ken.Yang
* @Date 2021/8/16 17:05
*/
@Configuration
public class FilerAutoConfiguration {

@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({UserId.class, UserMobile.class}) //多个用逗号隔开
protected static class ArgumentResolverAutoConfiguration extends WebMvcConfigurationSupport {

public ArgumentResolverAutoConfiguration() {
}

@Override
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
//可添加多个
argumentResolvers.add(new UserIdMethodArgumentResolver());
argumentResolvers.add(new UserMobileMethodArgumentResolver());
}
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12

@Validated
@RestController
public class TestAuthController {
@UserAuthenticate
@GetMapping(value = Urls.Test.TEST)
public Response testAuth(@UserId Long userId,@UserMobile String userMobile) {
System.out.println("userId : "+ userId + " userMobile :" + userMobile);
return new Response();
}
}

浏览器输入地址 后台打印

userId : 1 userMobile :18888888888

Prev:
Spring 定时任务
Next:
Springboot之HandlerInterceptor拦截器(一)
catalog
catalog