這是一種有關(guān)記住我功能的新實(shí)現(xiàn)方式
在傳統(tǒng)的前后端不分離項(xiàng)目中,大家在登錄界面應(yīng)該經(jīng)常能看到記住我這個(gè)功能,這個(gè)功能本質(zhì)上是為了讓用戶(hù)能在一段較長(zhǎng)時(shí)間內(nèi)不再重復(fù)登錄,在以前的實(shí)現(xiàn)方案中,大家多使用 cookie 實(shí)現(xiàn),本文給大家介紹在引入了 spring-session-redis 的項(xiàng)目中,使用一種新的實(shí)現(xiàn)方式,直接設(shè)置 redis 中用戶(hù) session 的有效期來(lái)實(shí)現(xiàn)。
本文使用 newbeepro 項(xiàng)目作為示例,給大家演示記住我功能的具體實(shí)現(xiàn)。項(xiàng)目地址:https://github.com/wayn111/newbee-mall-pro
本文大綱如下,
圖片
1. spring-session 的 yml 配置
圖片
在使用 spring-session 后,我們可以在 spring 的 yml 文件中設(shè)置 session 在 redis 中的 key 前綴,在 newbeepro 項(xiàng)目中,我們?cè)O(shè)置為 newbee_mall,然后我們?cè)O(shè)置過(guò)期時(shí)間 3600 秒,也就是一小時(shí)。
2. spring-session 的默認(rèn)序列化方式
@Configuration
public class CacheConfig implements CachingConfigurer {
/**
* 指定spring-session的默認(rèn)序列化方式
*
* @return RedisSerializer
*/
@Bean("springSessionDefaultRedisSerializer")
public RedisSerializer<Object> redisSerializer() {
return valueSerializer();
}
private RedisSerializer<Object> valueSerializer() {
return new GenericFastJsonRedisSerializer();
}
}添加 RedisSerializer 類(lèi)的 bean 實(shí)例,并且設(shè)置 bean 名稱(chēng)是 springSessionDefaultRedisSerializer。注意 bean 名稱(chēng)必須是 springSessionDefaultRedisSerializer。
這一步不是必須的,作用是可以設(shè)置 spring-session-redis 的默認(rèn)序列化實(shí)現(xiàn)。當(dāng)我們?cè)O(shè)置為 fastjson 的序列化方式時(shí),就可以讓我們方便查看 redis 客戶(hù)端。
3. 打開(kāi)登錄頁(yè)面
圖片
當(dāng)用戶(hù)打開(kāi) newbeepro 項(xiàng)目前端頁(yè)面時(shí),用戶(hù) session 就已經(jīng)在 redis 中保存了下來(lái),這一點(diǎn)我們通過(guò)查看 redis 客戶(hù)端發(fā)現(xiàn),此時(shí)用戶(hù)的 session 信息已經(jīng)存在,并且有效期是 3600 秒與我們 yml 配置的過(guò)期時(shí)間是一致的。
圖片
4. 后端登錄接口如何實(shí)現(xiàn)記住我
@ResponseBody
@PostMapping("/login")
public R doLogin(MallUserVO mallUserVO,
@RequestParam("destPath") String destPath,
HttpSession session) {
R success = R.success();
MallUser user = mallUserService.getOne(Wrappers.<MallUser>lambdaQuery()
.eq(MallUser::getLoginName, mallUserVO.getLoginName())
.eq(MallUser::getPasswordMd5, Md5Utils.hash(mallUserVO.getPassword())));
if (user == null) {
return R.error("賬戶(hù)名稱(chēng)或者密碼錯(cuò)誤");
}
if (user.getLockedFlag() == 1) {
return R.error("該賬戶(hù)已被禁用");
}
BeanUtils.copyProperties(user, mallUserVO);
session.setAttribute(Constants.MALL_USER_SESSION_KEY, mallUserVO);
String namespace = environment.getProperty("spring.session.redis.namespace");
String sessionKey = namespace + ":sessions:" + session.getId()
int timeout = Integer.parseInt(environment.getProperty("spring.session.timeout"));
if (mallUserVO.isRememberme()) {
redisCache.setCacheMapValue(sessionKey, "maxInactiveInterval", timeout * 24 * 7);
} else {
redisCache.setCacheMapValue(sessionKey, "maxInactiveInterval", timeout);
}
if (StringUtils.isNotEmpty(destPath) && StringUtils.contains(destPath, "=")) {
success.add("destPath", destPath.split("=")[1].substring(1));
}
return success;
}在登錄接口中,我們可以通過(guò) mallUserVO.isRememberme() 方法來(lái)判斷用戶(hù)是否點(diǎn)擊了記住我按鈕,在前面的第三步中,我們可以看到用戶(hù)的 session 在 redis 中 的 key 名稱(chēng)是 newbee_mall:sessions:c3fd288e-c9c2-47e6-961b-a5e1e0a3205e。
這里給大家講解一下這個(gè) key 的拼接邏輯。
圖片
OK,根據(jù)這個(gè)拼接邏輯,我們拼接 session key 的實(shí)現(xiàn)代碼就是,
String namespace = environment.getProperty("spring.session.redis.namespace");
String sessionKey = namespace + ":sessions:" + session.getId()然后大家在用戶(hù) session key 的 hash 內(nèi)容里可以發(fā)現(xiàn)有一個(gè) hashKey 名稱(chēng)是 maxInactiveInterval,它就是用戶(hù) session 的有效期屬性,我們可以通過(guò)改變 maxInactiveInterval 的屬性值來(lái)延長(zhǎng)用戶(hù) session 的有效期,以此來(lái)實(shí)現(xiàn)記住我功能。
圖片
那我們就可以通過(guò) redisCache 實(shí)例來(lái)直接設(shè)置用戶(hù) session 的有效期,代碼如下,
redisCache.setCacheMapValue(sessionKey, "maxInactiveInterval", timeout * 24 * 7)5. 登錄成功
當(dāng)用戶(hù)勾選了記住我按鈕,登錄成功后,我們來(lái)看下 redis 客戶(hù)端,
圖片
OK,大功告成。
總結(jié)一下
本文給大家講解了在使用 spring-session-redis 的項(xiàng)目中,如何通過(guò)延長(zhǎng)用戶(hù) session 的有效期來(lái)達(dá)到記住我功能的一致效果。
大家在學(xué)習(xí)本文后,也可以把記住我功能應(yīng)用到自己的項(xiàng)目中,本文實(shí)例代碼都在 newbeepro 項(xiàng)目中可以找到。


























