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