分布式系列 单点登录和session共享实现

来源:互联网 发布:常见web前后端数据交互 编辑:程序博客网 时间:2024/05/16 09:08

         上篇文章简单的描述了下单点登录的场景和解决单点登录问题的几套方案。

   本文将从具体实现层面剖析如何实现SSO和session共享。

   假设我们有三个子系统:Project1;Project2,Project 3,此时,访问每个子系统都会有自己的会话。只要他们之间互认了sessionID,我们就能任意在个子系统之间穿梭访问。

                   


    这是SSO的一张流程图。比较详细的上描述了用户从登陆页面到访问用户中心、订单系统的过程,采用了redis保存会话的共享机制,也是当前比较常用的一套实现方案。

    该方案具有明显的好处:redis存取速度快,不会网出现多个节点session复制的问题,且效率高。

    查询数据校验:

    

@Servicepublic class UserRegisterServiceImpl implements UserRegisterService {@Autowiredprivate TbUserMapper userMapper;@Overridepublic SystemResult checkInfo(String value, String type) throws Exception {boolean result = false;//type为类型,可选参数1、2、3分别代表username、phone、emailif ("1".equals(type)) {result = checkUserName(value);} else if ("2".equals(type)) {result = checkPhone(value);} else if ("3".equals(type)) {result = checkEmail(value);}//返回结果if (result) {return TaotaoResult.ok(result);}throw new DataException("此数值已经存在");}private boolean checkUserName(String userName) throws Exception {//创建查询条件TbUserExample example = new TbUserExample();Criteria criteria = example.createCriteria();criteria.andUsernameEqualTo(userName);List<TbUser> list = userMapper.selectByExample(example);//判断结果中是否存在if (list == null || list.isEmpty()) {return true;}return false;}private boolean checkPhone(String phone) throws Exception {//创建查询条件TbUserExample example = new TbUserExample();Criteria criteria = example.createCriteria();criteria.andPhoneEqualTo(phone);List<TbUser> list = userMapper.selectByExample(example);//判断结果中是否存在if (list == null || list.isEmpty()) {return true;}return false;}private boolean checkEmail(String email) throws Exception {//创建查询条件TbUserExample example = new TbUserExample();Criteria criteria = example.createCriteria();criteria.andEmailEqualTo(email);List<TbUser> list = userMapper.selectByExample(example);//判断结果中是否存在if (list == null || list.isEmpty()) {return true;}return false;}}


    用户注册实现:

@Overridepublic SystemResult register(TbUser user) throws Exception {//有效性验证if (StringUtils.isBlank(user.getUsername())) {throw new DataException("用户名不能为空");}if (StringUtils.isBlank(user.getPassword())) {throw new DataException("密码不能为空");}if (StringUtils.isBlank(user.getPhone())) {throw new DataException("手机不能为空");}//转换md5user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));//完善user信息user.setCreated(new Date());user.setUpdated(new Date());//添加到数据库userMapper.insert(user);return SystemResult.ok();}


    登录实现:

@Servicepublic class UserLoginServiceImpl implements UserLoginService {@Autowiredprivate TbUserMapper userMapper;@Autowiredprivate JedisCluster jedisCluster;@Value("${USER_TOKEN_KEY}")private String USER_TOKEN_KEY;@Value("${SESSION_EXPIRE_TIME}")private Integer SESSION_EXPIRE_TIME;@Overridepublic SystemResult login(String username, String password) throws Exception {//根据用户名查询用户信息TbUserExample example = new TbUserExample();Criteria criteria = example.createCriteria();criteria.andUsernameEqualTo(username);List<TbUser> list = userMapper.selectByExample(example);if (null == list || list.isEmpty()) {throw new DataException("用户不存在");}//核对密码TbUser user = list.get(0);if (!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())) {throw new DataException("密码错误");}//登录成功,把用户信息写入redis//生成一个用户tokenString token = UUID.randomUUID().toString();jedisCluster.set(USER_TOKEN_KEY + ":" + token, JsonUtils.objectToJson(user));//设置session过期时间jedisCluster.expire(USER_TOKEN_KEY + ":" + token, SESSION_EXPIRE_TIME);return SystemResult.ok(token);}}


      用户查询:

@Servicepublic class UserTokenServiceImpl implements UserTokenService {@Autowiredprivate JedisCluster jedisCluster;@Value("${USER_TOKEN_KEY}")private String USER_TOKEN_KEY;@Value("${SESSION_EXPIRE_TIME}")private Integer SESSION_EXPIRE_TIME;/** * 根据token取用户信息 */@Overridepublic SystemResult getUserByToken(String token) throws Exception {//从redis中取用户信息String userJson = jedisCluster.get(USER_TOKEN_KEY + ":" + token);if (StringUtils.isBlank(userJson)) {throw new DataException("该用户已过期");}//把json转换成user对象TbUser user = JsonUtils.jsonToPojo(userJson, TbUser.class);//更新用户有效期jedisCluster.expire(USER_TOKEN_KEY + ":" + token, SESSION_EXPIRE_TIME);return SystemResult.ok(user);}}

        后续登录拦截器的配置,就不在此多说了。

阅读全文
0 0
原创粉丝点击