问答平台(2),检查登录状态

问题背景

如果用户没登录,拒绝直接访问设置用户的URL,服务器端需要有判断机制。

使用拦截器

1
2
- 在方法前标注自定义注解;
- 拦截所有请求,只处理带有该注解的方法。

自定义注解

常用的元注解

1
2
3
4
- @Target: 声明自定义注解可以作用在哪个位置
- @Retention:声明自定义注解有效的时间(运行时有效 or 编译时有效)
- @Document:生成文档时是否带上注解
- @Inherited:用于继承,指定子类是否继承父类的注解
1
2
3
4
5
// 包: annotation
// LoginRequired.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired { }

如何读取注解(通过反射)

1
2
- Method.getDeclareAnnotations()
- Method.getAnnotation(Class<T> annotationClass)

在方法前标注自定义注解

1
2
3
4
5
6
7
8
9
10
11
12
// UserController.java
@LoginRequired
@RequestMapping(path = "/setting", method = RequestMethod.GET)
public String getSettingPage(Model model) {

}

@LoginRequired
@RequestMapping(path = "/upload", method = RequestMethod.POST)
public String uploadHeader(MultipartFile headerImage, Model model) {

}

拦截器的定义

只有访问的方法加注解(检查是否用户登录),避免在Config里面增加过多的拦截配置。

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
// 包: controller -> interceptor
// LoginRequiredInterceptor.java
@Component
public class LoginRequiredInterceptor implements HandlerInterceptor {

@Autowired
private HostHolder hostHolder;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 拦截到的是一个方法
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 读到注解,需要登录才能访问
LoginRequired loginRequired = method.getAnnotation(LoginRequired.class);
// 访问该方法,并且用户没登录
if (loginRequired != null && hostHolder.getUser() == null) {
// 重定向到登录页面
response.sendRedirect(request.getContextPath() + "/login");
return false;
}
}
return true;
}
}

拦截器的配置

将拦截器 loginRequiredInterceptor 加入 registry 对象

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
// 包: config
// WebMvcConfig.java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

@Autowired
private AlphaInterceptor alphaInterceptor;

@Autowired
private LoginTicketInterceptor loginTicketInterceptor;

@Autowired
private LoginRequiredInterceptor loginRequiredInterceptor;

// 添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//将拦截器加入registry对象
registry.addInterceptor(alphaInterceptor)
.excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg")
.addPathPatterns("/register", "/login");

registry.addInterceptor(loginTicketInterceptor)
.excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg");

registry.addInterceptor(loginRequiredInterceptor)
.excludePathPatterns("/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg");
}
}

问答平台(2),检查登录状态
https://lcf163.github.io/2020/05/01/问答平台(2),检查登录状态/
作者
乘风的小站
发布于
2020年5月1日
许可协议