问题:如何保证用户登陆一次后,可以免密登录?
问题说明:由于集群的使用,用户不能实现Session的共享.但是有些数据必须需要用户登陆后才能操作.如何解决Session共享问题.
sso单点登陆原理:
1.当用户进行第一次登陆时通过jt-web访问jt-sso单点登录系统
2.sso单点登录系统.会校验用户名和密码.如果用户名和密码正确的则生成一份秘钥.并且将用户的信息转化为JSON数据.之后将秘钥和JSON数据保存到redis中.
3.将秘钥返回给客户端程序(web),需要将秘钥进行保存.保存到浏览器的Cookie中
4.当用户再次访问服务器时,首先检测用户是否有Cookie,如果有则获取秘钥.通过redis查询获取用户的真实的信息.从而实现免密登录.
判断用户信息是否为空的两种方式
!StringUtils.isEmpty(userJSON)
userJSON == null
用户信息查询成功和失败
SysResult.oK(userJSON)或SysResult.oK(ticket)或SysResult.oK(list);
SysResult.build(201,”查询失败“);
1.用户注册
1.页面通用跳转
注册: /user/register.html
登陆: /user/login.html
前台controller
@Controller
@RequestMapping("/user")
public class UserController {
//实现页面的通用跳转
@RequestMapping("/{module}")
public String module(@PathVariable String module){
return module;
}
}
httpClient工具类doPost
1.String uri
2.Map<String,String> params
3.String charset
4.HttpPost httpPost
5.String result
6.List<NameValuePair> parameters
7.BasicNameValuePair valuePair
8.UrlEncodedFormEntity formEntity
9.CloseableHttpResponse httpResponse
if(StringUtils.isEmpty(3)){ //判断字符集是否为空
charset=“UTF-8”;
4=1 //新建对象参数传入
4.setconfig(requestConfig);
for (Map.Entry<String,String> entry : 2.entrySet()){
7=new BasicNameValuePair(entry.getKey(),entry.getValue());
6.add(7);
}
8=6+3 //新建对象参数传入
4.setEntity(8);
}
9=httpClient.execute(4);
if(9.getStatusLine().getStatusCode()==200){
5=EntityUtils.toString(9.getEntity(),3);
得到5
前台Service
1.String url=“http://sso.xx.com/register”
2.Map<String,String> params //put入用户名,密码,手机号,邮箱等用户信息
3.String jsonData
4.SysResult sysResult
3=httpClient.doPost(1,2);
4=objectMapper.readValue(3,4.class);
if(4.getStatus()=200){
得到 (String)4.getData();
}
后台Service
需求:封住用户信息入库数据,对密码加密处理
1.User user
2.String md5PassWord
2=DigestUtils.md5Hex(1.getPassword());
1.setPassword(2);
1.setEmail(1.getPhone()); //用电话代替email,以便存入mysql不报错
1.setCreated(new Date());
1.setUpdated(1.getCreated());
userMapper.insert(1);
2.用户登陆
需求:当用户登陆时,先判断用户信息是否正确,不正确抛出异常。正确则生成密钥ticket,然后将用户信息转化为JSON数据,保存在redis中,设置超时时间两天
前台Controller login类
1.String ticket
2.Cookie cookie //可设置保存时间和设置所有用户共享cookie
3.HttpServletResponse response
1=userService.findUserByUP(username,password);
2=new Cookie(“XX_TICKET”,1);
2.setMaxAge(60*60*48);
2.setPath(“/“);
3.addCookie(2);
前台Service
除了url,与用户注册前台Service基本一致
后台Controller
1.User user //set入username和password
2.String ticket
2=userService.findUserByUP(1);
后台Service
1.User user
2.User userDB
3.String ticket
4.String userJSON
1.setPassword(DigestUtils.md5Hex(1.getPassword()));
2=userMapper.findUserByUP(1); //如果userDB为空就是用户名密码错误,抛出异常
3=“XX_TICKET”+System.currentTimeMillis()+1.getUsername();
3=DigestUtils.md5Hex(3); //生成密钥
4=objectMapper.writeValueAsString(2); //用户信息转化为JSON数据
jedisCluster.setex(3,60*60*48,4); //数据保存在redis上,超时时间2天
3.用户信息回显
需求:通过ticket获取redis中的user数据
后台Controller
1.String ticket
2.String callback
3.String userJSON
4.MappingJacksonValue jacksonValue
3=jedisCluster.get(1); //如果userDB为空就是用户名密码错误
4=3 //新建对象参数传入SysResult.oK(3)
4.setJsonpFunction(2);
得到4
4.用户登出
需求:当用户点击退出按钮时,应该删除redis缓存的用户信息,删除Cookie数据,然后将页面重定向到系统首页
前台Controller logout类
1.HttpServletRequest request
2.HttpServletResponse response
3.Cookie[] cookies
4.String ticket
5.Cookie XXCookie
3=1.getCookies();
for (Cookie cookie : cookies) {
if(“XX_TICKET".equals(cookie.getName())){ //遍历cookie数组找到当前用户信息的cookie
4=cookie.getValue(); //提取出当前用户信息的ticket
}
}
jedisCluster.del(4); //redis里删除当前用户信息的ticket
5=new Cookie(“XX_TICKET”,””);
5.setMaxAge(0); //cookie没有直接删除的方法,设置存活时间为0即为删除
5.setPath(“/”); //因为删除可能不生效,所以需要和登入时一直让cookie给所有用户共享
2.addCookie(5); //添加入响应对象
return “xx:/index.html”; //重定向到系统首页