Redis實戰-session共享之修改登錄攔截器

在上一篇中Redis實戰之session共享,我們知道了通過Redis實現session共享了,那麼token怎麼續命呢?怎麼刷新用戶呢?本來咱們就通過攔截器來實現這兩個功能。

凱哥自己開發的,領取外賣、打車、咖啡、買菜、各大電商的優惠券的公¥衆¥號。如下圖:

527c8a82983e56a30f4299fc76e1956a.png

 

正文開始

登錄攔截器優化:

先來看看現在攔截器情況:

6e649d0b148042138a07e16e7677f4df.png

攔截流程:

當攔截器攔截需要攔截到的url時候,纔會在攔截器中更新用戶token的過期時間。那如果,訪問了不被攔截的路徑,就不會給token續命的。這樣就會導致用戶token過期,而重新登錄的。這樣是不對的。

攔截了哪些路徑?在config/MvcConfig中

303aefeaefa995213ab88207d6a21c37.png

當訪問以上這些路徑的是,就不會自動更新用戶的token過期時間了。

優化:我們可以在現有攔截器簽名價格攔截器:

915557733da7a2752022aeb98d4dddd0.png

將獲取用戶,存放threadLocal及刷新token放到新的攔截器中。

第一個攔截器就叫做:刷新token攔截器;第二個攔截器就叫做:用戶攔截器

創建刷新token的攔截器:

import cn.hutool.core.bean.BeanUtil;
import com.hmdp.dto.UserDTO;
import com.hmdp.utils.UserHolder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.TimeUnit;
 
import static com.hmdp.constants.RedisConstants.LOGIN_USER_TOKEN_KEY;
import static com.hmdp.constants.RedisConstants.LOGIN_USER_TOKEN_TTL;
 
/**
 * @author 凱哥Java
 * @description 刷新用戶token的爛機器
 * @company
 */
public class RefreshTokenInterceptor implements HandlerInterceptor {
 
    private StringRedisTemplate stringRedisTemplate;
 
    /**
     * 因爲這個類不能被spring管理,所以不能直接注入RedisTemplate對象。通過構造函數傳遞
     *
     * @param stringRedisTemplate
     */
    public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1:從請求中獲取到token
        String token = request.getHeader("authorization");
        if (StringUtils.isEmpty(token)) {
            return true;
        }
        //2:基於token獲取redis中用戶對象
        String key = LOGIN_USER_TOKEN_KEY + token;
        Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);
        //3:判斷
        if (userMap.isEmpty()) {
            return true;
        }
        //將map轉對象
        UserDTO user = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);
        UserHolder.saveUser(user);
        //刷新token的過期時間
        stringRedisTemplate.expire(key, LOGIN_USER_TOKEN_TTL, TimeUnit.MINUTES);
        return true;
    }
 
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolder.removeUser();
    }
}

修改用戶攔截器:

import com.hmdp.utils.UserHolder;
import org.springframework.web.servlet.HandlerInterceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * @author 凱哥Java
 * @description 登錄攔擊器
 * @company
 */
public class UserInterceptor implements HandlerInterceptor {
 
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判斷是否需要攔截
        if (UserHolder.getUser() == null) {
            response.setStatus(401);
            return false;
 
        }
        return true;
    }
 
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolder.removeUser();
    }
}

修改MvcCofig。將兩個攔截器添加進去,並設置攔截順序:

import com.hmdp.interceptor.RefreshTokenInterceptor;
import com.hmdp.interceptor.UserInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
import javax.annotation.Resource;
 
/**
 * @author 凱哥Java
 * @description  mvn的配置-添加攔截器
 * @company
 */
@Configuration
public class MvcConfig implements WebMvcConfigurer {
 
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //登錄攔截器
        registry.addInterceptor(new UserInterceptor())
                .excludePathPatterns(
                        "/shop/**",
                        "/voucher/**",
                        "/shop-type/**",
                        "/upload/**",
                        "/blog/hot",
                        "/user/code",
                        "/user/login"
                ).order(1);
        //刷新token攔截器
        registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).addPathPatterns("/**").order(0);
    }
}

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章