用户注册
分析:当用户填写完成注册信息之后,将请求发送给前台服务器.之后前台消费者利用dubbo框架实现RPC调用。之后将用户信息传递给jt-sso服务提供者.之后完成数据的入库操作。
01.页面url分析
02.查看页面JS
$.ajax({
type : "POST",
url : "/user/doRegister",
contentType : "application/x-www-form-urlencoded; charset=utf-8",
data : {password:_password,username:_username,phone:_phone},
dataType : 'json',
success : function(result) {
if(result.status == "200"){
// 注册成功,去登录页
showMessage('注册成功,请登录!');
verc();
$("#registsubmit").removeAttr("disabled").removeClass().addClass("btn-img btn-regist");
isSubmit = false;
return;
}else{
showMessage('注册失败,请联系管理员!');
//alert('注册失败,请重新注册! ' + result.data );
}
}
03.编辑消费者
编辑消费者UserController
说明:编辑jt-web项目中的UserController
/**
* 实现用户新增
* url:/user/doRegister
* 参数: {password:_password,username:_username,phone:_phone},
* 返回值:SysResult对象~~~JSON串
*/
@RequestMapping("/doRegister")
@ResponseBody
public SysResult doRegister(User user) {
userService.saveUser(user);
return SysResult.success();
}
04.去修改dubbo的独立接口和相关系统的接口实现类
public interface DubboUserService {
void saveUser(User user);
}
//这是dubbo的实现类,使用dubbo的注解
@Service
public class DubboUserServiceImpl implements DubboUserService {
@Autowired
private UserMapper userMapper;
/**
* 实现用户注册. 用户注册时间/密码加密
*/
@Override
public void saveUser(User user) {
String md5Pass =
DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
user.setPassword(md5Pass)
.setEmail(user.getPhone())
.setCreated(new Date())
.setUpdated(user.getCreated());
userMapper.insert(user);
}
}
单点登陆
业务需求说明
1.如果用户登陆一次之后,则可以实现7天免密登陆.
2.如果用户在jt-web服务器登陆之后,则可以访问任意的其他系统 例如jt-manage/jt-sso/jt-cart/jt-order.
问题:如何保存用户的登陆信息.
分析说明:
如果按照常规手段,实现用户的登陆操作,将用户信息保存到session中,由于Session不能共享.则必然导致用户重复登陆
单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。这种方式减少了由登录产生的时间消耗,辅助了用户管理,是目前比较流行的。
01.SSO调用步骤:
1.用户输入用户名和密码完成用户信息校验时将数据发往JT-WEB服务器.
2.将用户信息通过JT-SSO系统完成数据库查询.
3.如果根据用户名和密码查询数据库时,如果发现用户信息有误.则返回错误信息.
如果后台调用一切正常,则开始单点登陆相关操作.
将用户信息保存到redis中,key设定UUID, value使用 userJSON数据,
4.如果保存redis成功之后,需要返回ticket信息(uuid);
5.用户使用Cookie保存用户ticket信息.
$.ajax({
type: "POST",
url: "/user/doLogin?r=" + Math.random(),
contentType: "application/x-www-form-urlencoded; charset=utf-8",
data: {username:_username,password:_password},
dataType : "json",
error: function () {
$("#nloginpwd").attr({ "class": "text highlight2" });
$("#loginpwd_error").html("网络超时,请稍后再试").show().attr({
"class": "error" });
$("#loginsubmit").removeAttr("disabled");
$this.removeAttr("disabled");
},
success: function (result) {
if (result) {
var obj = eval(result); //将JSON数据转化为js对象
if (obj.status == 200) {
obj.success = "http://www.jt.com";
var isIE = !-[1,];
if (isIE) {
var link = document.createElement("a");
link.href = obj.success;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
} else {
window.location = obj.success;
}
return;
}else{
$("#loginsubmit").removeAttr("disabled");
verc();
$("#nloginpwd").attr({ "class": "text highlight2" });
$("#loginpwd_error").html("账号或密码错误!").show().attr({
"class": "error" });
}
}
04.编辑UserController
说明:编辑jt-web项目的UserController。
/**
* 业务需求:实现用户登陆操作
* url地址:http://www.jt.com/userc?r=0.12008666779616362
* 参数: username/password
* 返回值类型: SysResult对象
*/
@RequestMapping("/doLogin")
@ResponseBody
public SysResult doLogin(User user,HttpServletResponse response) {
//1.将数据发往jt-sso系统完成校验
String uuid = userService.findUserByUP(user);
//2.需要校验uuid是否正确
if(StringUtils.isEmpty(uuid)) {
//用户名和密码不正确
return SysResult.fail();
}
//3.将用户信息写入cookie中.
Cookie cookie = new Cookie("JT_TICKET", uuid);
cookie.setMaxAge(7*24*3600); //设定cookie最大使用时间
cookie.setDomain("jt.com"); //在指定的域名中设定cookie数据共享
cookie.setPath("/"); //cookie的作用范围,从根目录开始.
response.addCookie(cookie);
return SysResult.success();
}
05.4编辑UserServiceImpl实现类
说明:编辑jt-sso的dubbo的实现类。
/**
* 核心业务逻辑: 根据用户名和密码查询数据库.
* 如果数据中有记录,则保存redis,之后返回uuid
* 如果数据库中没有记录,则返回null.
*/
@Override
public String findUserByUP(User user) {
//1.需要将密码进行加密
String md5Pass =
DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
user.setPassword(md5Pass);
//2.根据对象中不为null的属性,充当where条件
QueryWrapper<User> queryWrapper = new QueryWrapper<User>(user);
//查询用户的全部记录信息.
User userDB = userMapper.selectOne(queryWrapper);
if(userDB ==null) {
//3.如果userDB对象为null,则表示数据库中没有该记录.用户名密码错误.
return null;
}
//4.说明:用户名和密码正确的
String key = UUID.randomUUID().toString();
//5.为了保护用户隐私信息,手机号 email
userDB.setPassword("你猜猜!!!"); //userId/username
String userJSON = ObjectMapperUtil.toJSON(userDB);
jedisCluster.setex(key,7*24*3600, userJSON);
return key;
}
06.页面效果展现
07.实现用户信息回显
业务需求: 当用户登陆成功之后,用户信息需要进行回显. 您好:admin123
业务逻辑: 根据ticket信息,动态获取用户信息,之后实现数据的回显.
方法实现: 通过ajax动态查询后台的服务器数据.
方法1:dubbo调用
方法2:跨域访问
08.页面url分析
说明:通过分析当前请求,从jt-web的ajax进行跨域访问调用
09.页面JS分析
//当dataType类型为jsonp时,jQuery就会自动在请求链接上增加一个callback的参数
$.ajax({
url : "http://sso.jt.com/user/query/" + _ticket,
dataType : "jsonp", //发起JSONP的请求
type : "GET",
success : function(data){
//返回值SysResult对象
if(data.status == 200){
//把json串转化为js对象
var _data = JSON.parse(data.data);
var html =_data.username+",欢迎来到京淘![退出]a>";
$("#loginbar").html(html);
}
}
});
10.编辑JT-SSO的UserController
@Autowired
private JedisCluster jedisCluster;
/**
* 业务需求:根据ticket信息查询用户信息.
* url:http://sso.jt.com/user/query/58f8000b-bdec-40e6-910e-ac4f0cfb6cd8?
callback=jsonp1585296544219&_=1585296544497
* 参数:ticket信息
* 返回值: SysResult对象,用JSONPObject API包装
*
*/
@RequestMapping("/query/{ticket}")
public JSONPObject findUserByTicket(@PathVariable String ticket,String
callback) {
String userJSON = jedisCluster.get(ticket);
//判断查询是否正确
if(StringUtils.isEmpty(userJSON)) {
//如果为null,则表示数据,没有查询到.
SysResult sysResult = SysResult.fail();
return new JSONPObject(callback, sysResult);
}
//说明:用户信息没有错.
SysResult sysResult = SysResult.success(userJSON);
return new JSONPObject(callback, sysResult);
}
11.页面效果展现
JS与JSON串转化关系
1.服务返回的数据格式如下:
2.所以需要将json串手动的转化为JS对象
var _data = JSON.parse(data.data);
3.完成业务调用
var html =_data.username+",欢迎来到京淘![退出]a>";
用户退出操作
01.页面url分析
需求说明:
当用户点击退出操作时,应该跳转到系统首页.
同时删除 1.删除redis信息 2.删除cookie
url地址说明:
http://www.jt.com/user/logout.html
02.编辑UserController
说明:编辑jt-web项目的UserController
/**
* 业务需求:实现用户登出操作
* url: http://www.jt.com/user/logout.html
* 参数: 没有参数
* 返回值: 重定向到系统首页.
* 删除用户登陆凭证: 删除redis信息, 删除cookie信息.
*/
@RequestMapping("/logout")
public String logout(HttpServletRequest request,HttpServletResponse
response) {
//1.首先获取cookie中的值
Cookie[] cookies = request.getCookies();
//2.从数组中动态获取JT_TICKET数据
String ticket = null;
if(cookies !=null && cookies.length>0) {
for (Cookie cookie : cookies) {
if(cookie.getName().equals("JT_TICKET")) {
//3.动态获取cookie的值,这里的值不是对象,而是一个UUid,在redis集群中,value才是JSON化的java对象
ticket = cookie.getValue();
//4.同时删除cookie,因为没有delete操作,所以直接把cookie的生命周期设置为0秒
cookie.setMaxAge(0);
cookie.setDomain("jt.com");
cookie.setPath("/");
response.addCookie(cookie);
break;
}
}
}
//5.判断redis中是否存在该数据,如果存在直接删除
if(jedisCluster.exists(ticket)) {
jedisCluster.del(ticket)
}
return "redirect:/";
}