前面我们说了redis实现单点登入和redis实现登录拦截,redis实现登入拦截可以和session一起连用,保证用户必须在登入的条件下,才可以进行网站的访问。
1、项目需求
这篇文章介绍如何获取到我们需要的连接上下文信息,比如用户信息,可以存储一个全局变量,直接获取,这样在我们每次访问数据库的时候都可以获取到用户信息等我们需要的数据。这里需要注意的地方是,为了防止不同的用户登入存储出现线程不安全情况,所以有threalLocal来保存不同用户的信息,使用threalLocal的时候记得要remove掉缓存。
另外当有其他网站调用我们系统的时候,会出现没有登入人的情况,这时候可以用spring源码的接口InitializingBean在spring容器创建的时候,给我们当前系统默认登入管理员。
2、代码实例
先定义一个放上下文的util和实体类:
/**
* 全文上下文
*
* @author keying
*/
public class ContextUtil implements InitializingBean {
private static Context systemContext = new Context();
private static ThreadLocal<Context> threadLocalContext = new ThreadLocal<>();
public static Context getContext() {
return threadLocalContext.get();
}
public static void setContext(Context context) {
threadLocalContext.set(context);
}
public static void removeContext() {
threadLocalContext.remove();
}
public static Context getSystemContext(){
return systemContext;
}
@Override
public void afterPropertiesSet() throws Exception {
systemContext.setUserId("admin");
}
}
/**
* 上下文
*
* @author keying
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Context {
private String userId;
}
然后定义一个拦截器,拦截器里有我上篇文章redis实现单点登入的代码,已注释:
/**
* 登入拦截器
*
* @author keying
* @date 2021/6/11
*/
@Configuration
@Slf4j
public class LoginConfiguration implements WebMvcConfigurer {
@Resource
private RedisTemplate redisTemplate;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器
InterceptorRegistration interceptorRegistration = registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
/* log.info("登入拦截器启动!!");
log.info("session是否存在:{}", request.getSession().getAttribute("name"));
if (request.getSession().getAttribute("name") != null) {
redisTemplate.opsForValue().set("name", request.getSession().getAttribute("name"), 10,TimeUnit.SECONDS);
return true;
}
log.info("request.getContextPath():{}", request.getContextPath());
response.sendRedirect(request.getContextPath() + "/redis/single/system1");
//如果设置为false时,被请求时,拦截器执行到此处将不会继续操作
//如果设置为true时,请求将会继续执行后面的操作
return false;*/
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
log.info("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
log.info("afterCompletion");
}
});
//所有路径都被拦截
/* interceptorRegistration.addPathPatterns("/**");*/
//添加不拦截路径
interceptorRegistration.excludePathPatterns(
//"/redis/single/login_page",
"/redis/single/system1",
"/redis/single/system2",
"/redis/single/detection",
"/**/*.html",
"/**/*.js",
"/**/*.css",
"/**/*.woff",
"/**/*.ttf"
);
interceptorRegistration = registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//加上下文
Context context = getContext();
ContextUtil.setContext(context);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
//一定要记得remove
ContextUtil.removeContext();
}
});
//拦截所有路径
interceptorRegistration.addPathPatterns("/**");
}
private Context getContext() {
//给一个虚拟的登入者
return new Context("keying");
}
}