作为一个系统,存在有很多不想让访问进入的页面,如果任何人都可以访问到我们的操作页面,那么账号密码就失去了意义,因此,完成账户密码登录后,应增加一个登录拦截的功能,没有登录的用户只能访问到我们的登录注册页面
2023/11/7
1.编写一个过滤器
要实现登录拦截的功能,首先我们要先编写一个注册器,过程是所有的请求都要先经过我们的过滤器处理后,才能进入到指定资源,在写好的filter类中使用@WebFilter 并且在启动类中使用@ServletComponentScan扫描我们的filter,即可实现过滤请求的功能,下面是具体的代码编写:
@WebFilter(urlPatterns = "/*")
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String path = req.getRequestURI().substring(req.getContextPath().length());//在URI中过滤上下文路径
// 检查会话中是否有用户,且请求不是登录页面或静态资源
if (path.startsWith("/login") ||path.startsWith("/register")||path.startsWith("/toregister")||path.endsWith("/")) {
chain.doFilter(request,response);
}else{
//检查session
HttpSession session = req.getSession(false);//这里false的作用是不新建session
if (session == null || session.getAttribute("USER") == null) {
String encodeMessage = URLEncoder.encode("请登录后重试","UTF-8");
res.sendRedirect(req.getContextPath() + "/login"+"?message="+encodeMessage);
} else {
chain.doFilter(request, response);
}
}
}
}
在这里,我设置了所有根路径下的请求都要经过过滤,我们定义了一个AuthFilter也就是验证过滤,这里一定要implements Filter代表它是一个filter的实现类,然后重写他的dofilter方法,其中的参数是dofilter中自带的,具有一个servlet请求和响应,以及filterchain 过滤链,
首先我们将servlet强制转换为Http类型,然后获取一个当前路径,这里geturi是除了com后面的路径(也就是8080后面的),而我们需要的是一个单独的映射路径,所有需要去掉一个上下文路径,上下文路径的获取方式是req.getContentPath,举个例子就是
http://www.example.com/myapp/homepage?user=guest
这里/myapp/homepage就是URI,然后去掉上下文路径/myapp,我们只保留homepage,将其设置为path,如果path不是login或者register,我们允许游客访问的路径我们就要进行处理,如果是,那就放行,使用chain.dofilter,进入下一个过滤链,或者到达访问资源。如何进行处理,首先,我们定义一个session,将参数值设置为false,这个目的是,如果用户没有session那么我们不必为他新建一个session,节省资源,判断session是否为空,或者user不存在,也就是还没登录或者没有这个用户,那就重定向到login路径,并且返回一个message,这里的message我们是通过url 的形式返回的,因此需要实现encode一下
实现效果如下:
当我们输入index想要跳过登录进入系统时,
请求会进入我们的过滤器并拦截他
2023/11/8
2.将session会话存储到redis
前言:redis缓存数据库相比mysql来说具有更快的响应速度,并且可以设置TTL过期时间,将session会话放到缓存redis中是常见的策略,可以使得一段时间内登录过的用户无需重复验证
在springboot中有一个session管理的功能,首先我们导入相关的pom依赖
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
然后在配置文件中配置redis
spring.data.redis.port=6379
spring.data.redis.database=1
最后我们需要定义一个配置类,用来将其注册为一个bean,可以被springboot所管理
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 300)
public class RedisSessionConfig {
}
其中@EnableRedisHttpSession这个注解用于开启Spring Session的支持,并且指定session数据存储在Redis中。
做完这些,我们就可以正常在controller中使用session了
session.setAttribute("USER",username);
例如之前,我们在匹配过用户密码后给session的USER属性设置了一个值,可以在redis中显示出来,这里我们使用了一个redisinsight可视化软件,具体展现如下:
其中TTL我们设置的是每个会话存储300s,在300s内用户访问任何页面无需重新验证,300s后session消失,dofilter方法会重新导向到登录页面,自此完成了登录验证拦截并且存在过期时间的所有功能。