本次目标
在传统的SpringBoot项目开发过程中,是将用户的登录状态保存在Session中的。但是基于微服务的项目各模块都是一个单独的SpringBoot项目,这时Session共享就是首要解决的问题。
有一种思路,就是将Session在每个服务器中同步一份,但是这种方式有一种很明显的缺陷,就是数据冗余——每个服务器存在相同的数据。
另外一种思路,就是将会话信息保存在第三方应用中,每个微服务都从这个第三方服务中设置和获取会话信息,这就用到了Redis技术。
使用Redis实现Session的会话存储功能,结构类似于这样:
准备工作
创建RedisCluster集群。参考Redis6.0.4 服务器集群搭建
前端逻辑
首页
index.html
总体思路:在HTML页面没加载完成时,就判断本地有没有Cookie键为CommonUser的Cookie。如果存在,继续后面的逻辑。如果不存在,直接跳转到登录页面;
<script>
//不用等到jquery下载完毕,用原生js处理更快
var havec=false;
var cookieV;
var strcookie = document.cookie;//获取cookie字符串
var arrcookie = strcookie.split(";");//分割
//遍历匹配
for ( var i = 0; i < arrcookie.length; i++) {
var arr = arrcookie[i].split("=");
if(arr[0].trim()=="commonUser"){
havec=true;
//存储登录信息的cookie值
cookieV=arr[1].trim();
}
}
if(!havec){
window.location.href='http://localhost/admin/pages/main/login.html';
}
</script>
登录页
login.html
总体思路:点击登录按钮,将用户名和密码通过ajax提交给用户微服务,如果鉴权成功,用户名密码无误,就将用户的信息保存到Redis,并将键(key)封装到Cookie中返回浏览器。登录成功后跳转到index.html,登录失败提示失败信息。
<script>
function checkForm(){
$("#sub").attr("enable",false);
$("#sub").html("<i class=\"fas fa-1x fa-sync-alt fa-spin\"></i> Sign In");
var userName=$("input[name='userName']").val();
var psw=$("input[name='psw']").val();
$.post("http://localhost/user/adminLogin",{"userName":userName,"psw":psw},function (result) {
$("#sub").attr("enable",true);
$("#sub").html("Sign In");
if(result.status!=200){
alert(result.msg);
}else{
$(window).attr('location','http://localhost/admin');
}
}).fail(function () {
alert("登录异常");
});
return false;
}
</script>
后端逻辑逻辑
业务层:
...
if(!ifOk){
return SysResult.build(500,"无权访问!",null);
}
//安全起见,将用户密码值为空
commonUser.setPsw("");
String cookieK="cookiek_"+commonUser.getUserName()+System.currentTimeMillis();
ValueOperations<String, String> stringValueOperations = stringRedisTemplate.opsForValue();
try {
String commonUserJson=objectMapper.writeValueAsString(commonUser);
stringValueOperations.set(cookieK,commonUserJson,3, TimeUnit.HOURS);
} catch (JsonProcessingException e) {
e.printStackTrace();
return SysResult.build(500,"登录异常",null);
}
...
控制层:
@RequestMapping("adminLogin")
public SysResult adminLogin(@Param("userName") String userName,@Param("psw") String psw, HttpServletRequest request, HttpServletResponse response){
SysResult sysResult= userService.adminLogin(userName,psw,"user/adminLogin");
if(sysResult.getStatus()==200){
String cookiek = (String) sysResult.getData();
CookieUtils.setCookie(request,response,"commonUser",cookiek);
}
return sysResult;
}
由于篇幅原因,不合适展示所有代码,这里主要做简单的梳理,方便大家对源码进行阅读和理解。
代码地址:https://gitee.com/zhaoliwen/JD_ALL.git