一.sso工程的搭建
1.创建e3-sso聚合工程,以及子工程:e3-sso-interface,e3-sso-service,接着创建e3-sso-web
2.内容可参照其他的聚合工程和web工程
二.注册用户数据校验
》当用户在用户名,手机号,邮箱的输入框输入数据后,发送一个ajax请求到后台校验是否重复
》在sso-service创建方法checkData(Integer type,String value)校验数据,代码如下:
public class RegisterServiceImpl implements RegisterService { private TbUserMapper tbUserMapper; public E3Result checkData(Integer type, String value) { //创建查询条件对象 TbUserExample example = new TbUserExample(); Criteria criteria = example.createCriteria(); //判断数据类型,添加不同的查询条件 //判断是否用户名 //判断是否手机号 //判断是否邮箱 if( type == 1 ) { criteria.andUsernameEqualTo(value); }else if(type == 2){ criteria.andPhoneEqualTo(value); }else if(type == 3) { criteria.andEmailEqualTo(value); }else { return E3Result.build(400,"数据类型错误"); } //执行查询,返回结果 List<TbUser> list = tbUserMapper.selectByExample(example); //判断结果是否为空 //空返回true //不空返回false if( list.size() >0 && list != null) { return E3Result.ok(false); } return E3Result.ok(); } }
三.用户注册
》service层的注册方法
public E3Result regist(TbUser tbUser) { //补全信息 tbUser.setUpdated(new Date()); tbUser.setCreated(new Date()); //密码加密 String md5Pass = DigestUtils.md5(tbUser.getPassword().getBytes()).toString(); tbUser.setPassword(md5Pass); //插入数据 tbUserMapper.insert(tbUser); //返回结果 return E3Result.ok(); }
四.用户登录
》传统的登录流程:客户端发送登录请求 ->tomcat校验正确生成一个sessionId并添加到cookie里->返回给客户端
》现在由于是单点登录系统,不再使用tomcat的session,由于考虑到session的结构和redis存储的结构是一样的,所以将原本存储再session的数据改为在redis中,这样还有个好处是当用户想查询自己的相关信息时,无需查询数据库,直接走缓存!
》key应该是token(sessionID),value为用户的信息(对象转换为json字符串);token可使用uuid生成
》需要将token添加到cookie中,以便下次带回,但是添加cookie的操作由表现层完成,因为response不在service层
service:
@Override public E3Result userLogin(String username, String password) { // 1、判断用户和密码是否正确 //根据用户名查询用户信息 TbUserExample example = new TbUserExample(); Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo(username); //执行查询 List<TbUser> list = userMapper.selectByExample(example); if (list == null || list.size() == 0) { //返回登录失败 return E3Result.build(400, "用户名或密码错误"); } //取用户信息 TbUser user = list.get(0); //判断密码是否正确 if (!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())) { // 2、如果不正确,返回登录失败 return E3Result.build(400, "用户名或密码错误"); } // 3、如果正确生成token。 String token = UUID.randomUUID().toString(); // 4、把用户信息写入redis,key:token value:用户信息 user.setPassword(null);//由于可能用户会查询自己的相关信息,密码可不用缓存在redis中 jedisClient.set("SESSION:" + token, JsonUtils.objectToJson(user)); // 5、设置Session的过期时间 jedisClient.expire("SESSION:" + token, SESSION_EXPIRE); // 6、把token返回 return E3Result.ok(token); }
controller:
@RequestMapping(value="/user/login", method=RequestMethod.POST) @ResponseBody public E3Result login(String username, String password, HttpServletRequest request, HttpServletResponse response) { E3Result e3Result = loginService.userLogin(username, password); //判断是否登录成功 if(e3Result.getStatus() == 200) { String token = e3Result.getData().toString(); //如果登录成功需要把token写入cookie CookieUtils.setCookie(request, response, TOKEN_KEY, token); } //返回结果 return e3Result; }
五.根据token取用户信息
service:
controller:
六.跨域问题
》在浏览器里,从本页面发送js请求到其他不同的ip,不同的域名,不同的端口中满足其一,就会被浏览器所拦截(你请求实际是发出去了,服务器也响应了,就是浏览器拦截响应的数据)
》解决思路:虽然浏览器由跨域的限制,但是对js文件的跨域请求是不拦截的,所以我们可以通过script标签发送我们的请求
》好消息是预定义函数和参数等待,jquery已经帮我们做了,只需要在发送ajax请求时,指明请求为jsonp即可
》服务端controller代码的实现有两种: