Cookie生成与处理

首先写一个cookie加密的方法,目前的思路是根据用户名和密码生成加密后的cookie token,加密规则 Base64(username) + "|" + md5(username+password) 生成一段结果字符串

public static String encryUserCookieMd5(String username,String password){
    String str = username+password;
    String md5_username_password = DigestUtils.md5DigestAsHex(str.getBytes());
    String base64_username = Base64Utils.encodeToString(username.getBytes(StandardCharsets.UTF_8));
    return base64_username + "|" + md5_username_password;
}

然后写一个解密的方法,读取request中的cookie,传入的cokie字符串的值 通过 “|”将cookie字符串分割为两个部分 将第一部分加密的username进行解密,并返回这个username值

public static String decryUserCookieMd5(String cookie){
    String[] cookies = cookie.split("\\|");
    byte[] username = Base64Utils.decode(cookies[0].getBytes(StandardCharsets.UTF_8));
    return new String(username);
}

登录请求拦截

注册一个登录拦截器 LoginIntercepter ,对登录请求进行拦截处理,首先判断session中是否以及存在登录了此用户,如果登录则直接返回true,代表登录成功,如果没有的话就获取cookie,根据上方的cookie编码解码规则,得到cookie中的用户名,然后根据用户名从数据库中查找用户,根据查找的这个用户的用户名和密码再次进行编码加密,与cookie原始值进行比对,如果完全想等则认为此用户可以使用cookie登录成功。

public class LoginIntercepter implements HandlerInterceptor {

    @Autowired
    UserRepository userRepository;
    
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 登录检查逻辑
        HttpSession session = request.getSession();
        Object loginuser = session.getAttribute("LoginUser");
        if (loginuser != null) {
            return true;
        } else {
            // 获得cookie
            Cookie[] cookies = request.getCookies();
            Integer hase_cookie_user = 1;
            // 没有cookie信息,则重定向到登录界面
            if (null != cookies) {
                // 获取cookie里面的一些用户信息
                for (Cookie item : cookies) {
                    // 根据获取的cookie值,将值进行解密获取username
                    // 然后从数据库中获取用户名和密码并进行加密操作
                    // 如果加密后的字符串和当前传入的字符串相同,则代表此用户可通过cookie登录
                    if ("cookie_username".equals(item.getName())) {
                        String cookie_username = item.getValue();
                        String uname = SecMd5.decryUserCookieMd5(cookie_username);
                        log.info("uname:" + uname);
                        User user = userRepository.findByUsernameEquals(uname);
                        if (user != null) {
                            String user_name = user.getUsername();
                            String user_password = user.getPassword();
                            if (SecMd5.encryUserCookieMd5(user_name, user_password).equals(cookie_username)) {
                                session.setAttribute("LoginUser", user);
                                log.info("cookie 登录");
                                return true;
                            }
                            break;
                        }

                    }
                }
            }
        }
        session.setAttribute("loginmsg", "未登录");
        response.sendRedirect("/");
        return false;
    }
    // ....其他方法省略
}

没有cookie的时候,对登录后的账号进行编码加密,生成一段cookie值

session.setAttribute("LoginUser", user);
// 保存cookie,实现自动登录
Cookie cookie_username = new Cookie("cookie_username", SecMd5.encryUserCookieMd5(uname,upwd));
// 设置cookie的持久化时间,1天
cookie_username.setMaxAge( 24 * 60 * 60);
// 设置为当前项目下都携带这个cookie
cookie_username.setPath(request.getContextPath());
// 向客户端发送cookie
response.addCookie(cookie_username);

@Autowired 自动注入失败,结果为null

注入失败的原因是因为HandlerInterceptor类在Spring框架中被new过,new 过的对象不会交给Spring容器管理 所以里面的 service或者dao会注入失败。

解决方式

在WebMvcConfigurer 配置中使用@Bean注解,将登录拦截器注入进去

@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
    @Bean
    public LoginIntercepter setLoginIntercepterBean(){
        log.info("注入拦截器");
        return new LoginIntercepter();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {  // 全局过滤器 判断是否登录
        registry.addInterceptor(setLoginIntercepterBean()) 
                .addPathPatterns("/**")
                .excludePathPatterns(
                        "/",
                        "/login"
                        // 白名单路径
                );
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {   // 映射资源url与本地资源路径
        // 路径映射
    }
}

参考文章

SpringBoot之Filter/HandlerInterceptor 中注入service为null解决方案_临窗,听雨声的博客-CSDN博客

springboot @Autowired 注入为null 的原因与解决方式_Jack2013tong的博客-CSDN博客_autowired注入为null

如果觉得我的文章对你有用,请随意赞赏