携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情
检查登录状态
用户没登陆的时候有一些功能是不能访问的,但是如果我们后台没有“检查登录状态”,在没登录的情况下通过在地址栏输入http://localhost:8080/community/user/setting 可以访问 “上传文件”的功能,这种行为会对我们的系统造成很大的安全隐患,所以我们需要去杜绝这种行为。
因此不是说不让他(她)看见就行,得一定是他(她)无论如何都访问不到才可以。
解决:在用户没有登录的时候,在访问不可以访问的功能的时候,应该在服务端进行一个判断,登陆了可以访问,没登录拒绝。
可以想到的是,很多功能都需要这样的判断,众多请求都有一样的逻辑,我们用拦截器处理。
拦截器拦截哪个方法有两种设置:
一种是写拦截器的配置文件
还有一种是拦截哪个的话在哪个方法/类上加上注解(这种方式我们需要自定义注解)
这两种可以只使用一种,也可以两种都用,接下来我们两种方式都用开发一下检查登录状态的拦截器。
1. 自定义注解
自定义注解
我们在定义自己的注解的时候需要用元注解定义我们自己的注解
- @Target
- 用来声明自定义的注解可以写在哪个位置:类 / 方法
- @Retention
- 用来声明自定义注解保留的时间或有效时间:编译时有效 / 运行时有效
- @Document
- 用来声明自定义注解在生成文档时要不要把这个注解也带上去
- @Inherited
- 表示这个自定义注解可不可以被子类继承
自定义注解的时候前两个元注解基本上是必须写的
自定义注解:
@Target(ElementType.METHOD) // 表示自定义的这个注解应该写在方法之上
@Retention(RetentionPolicy.RUNTIME) // 表示这个注解在程序运行的时候有效
public @interface LoginRequired {
}
这个注解是用来标识这个方法它需不需要在登陆的状态下才能访问,
这个注解相当于”标识“的作用,打上这个标记就必须登录才能访问,不打上这个标记表示随便
标记一下,哪些请求需要登录以后才能访问呢:
2. 书写拦截器
拦截器
接下来使用拦截器去拦截带有注解的方法,在拦截到方法之后判断登没登录,登录了可以,没登录拒绝
@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){
// 不等于 null 表示这个方法是需要登录才能访问的
// 但是 hostHolder.getUser() == null 表示没有登录
// 这个时候应该拒绝后续的请求,强制重定向到登录页面 request.getContextPath() 表示取到应用的路径
response.sendRedirect(request.getContextPath() + "/login");
return false;
}
}
return true;
}
}
3. 拦截器的配置文件
配置文件
最后我们配一下不拦截静态资源的请求,其他请求都拦截,从中找到带注解的。
不去处理静态的资源,而其他动态资源都处理,但处理的时候人为的筛选了带有注解的那一部分,其他的不管,这样的好处是希望它处理谁就在谁上加注解,而不是一个一个加路径(加路径也可以,两种方式都行)。
最后建议测试一下:
在没有登陆的状态下,输入 http://localhost:8080/community/user/setting 看它是否会跳转到