Java项目单点登录

目录

单点登录是什么?

单点登录案例使用方式解析。

B系统验证Code是否存在的代码

B系统提供的进行用户登录的代码


单点登录是什么?

        单点登录(SSO,Single Sign On),是在企业内部多个应用系统(如考勤系统、财务系统、人事系统等)场景下,用户只需要登录一次,就可以访问多个应用系统。

单点登录案例使用方式解析。

我们在A系统进行用户登录了之后,我们通过链接跳转到B系统时,首先带上Code,在我们B系统进行验证Code是否存在。

B系统验证Code是否存在的代码

示例代码

    @ApiOperation(value = "单点登录接口")
    @GetMapping("onePointLogin")
    public ResultVo<String> onePointLogin(@RequestParam String code,
                                          HttpServletResponse response) throws IOException {
        if(code == null || "".equals(code)){
            log.info("没有获取到code,进行重定向获取code");
            try {
                response.sendRedirect(RedirectUrl.LOGIN_URL_NOCODE);
            }
            catch (Exception e){
                e.printStackTrace();
            }
            return ResultVo.ok("ok");
        }

        //如果有登录信息code,重定向获取accessToken.
        log.info("获取到code,进行重定向获取accessToken");
        try {
            Map<String,Object> params = new HashMap<>();
            EasyOkHttpUtil easyOkHttpUtil = bdpUtil.callGet(RedirectUrl.LOGIN_URL_CODE+code, params);
            log.info("调用三方接口返回的数据为: " +easyOkHttpUtil );

            //获取具体的返回参数
            log.info("得到的access_token为: "+easyOkHttpUtil.getAccess_token() + " expires_in: " + easyOkHttpUtil.getExpires_in());

            /**
             * 如果当前token已过期,则重新进行获取token
             */
            if(easyOkHttpUtil.getExpires_in() <=0){
                log.info("当前获得的token已过期,重新获取");
                try {
                    //因为这里我不知道code,所以重定向到了获取code的接口,按理说是直接重定向到获取token的接口。
                    response.sendRedirect(RedirectUrl.LOGIN_URL_NOCODE);
                }
                catch (Exception ex){
                    ex.printStackTrace();
                }
                ResultVo.ok("token已过期,重新获取token");
            }

(1) 如果Code不存在,那么重定向到认证系统(A系统提供的获取code的接口)获取Code。重定向的地址我们会提供它重新调我们当前方法的地址(还是通过B系统提供的当前接口,来继续验证Code)。

public static final String LOGIN_URL_NOCODE =
            "https://qzx.zh/sso-api/oauth/authorize?client_id=qljq&response_type=code&redirect_uri=http://qzx.zh/qljq/onePointLogin&scope=read";

        上面的redirect_uri就是B系统的验证Code的接口

(2) 如果Code存在那么,我们就进行获取当前在A系统登录的token。

       Map<String,Object> params = new HashMap<>();
            EasyOkHttpUtil easyOkHttpUtil = bdpUtil.callGet(RedirectUrl.LOGIN_URL_CODE+code, params);
            log.info("调用三方接口返回的数据为: " +easyOkHttpUtil );

            //获取具体的返回参数
            log.info("得到的access_token为: "+easyOkHttpUtil.getAccess_token() + " expires_in: " + easyOkHttpUtil.getExpires_in());

        获取登录用户的token的接口也是A系统提供的接口,我们去调用三方接口获取到token,和过期时间,作为我们B系统的token。

同时还进行判断当前登录用户信息在B系统是否存在,因为需求在B系统需要展示用户信息。首先到我们自己的数据库查看用户信息是否存在,不存在的话就调用A系统提供的获取用户信息接口获取用户信息。

String userCode = userService.onePointLogin(easyOkHttpUtil.getUser(),easyOkHttpUtil.getAccess_token(),easyOkHttpUtil.getExpires_in());  //此时获取到的code是我们系统生成的token

            /**如果此时我们的数据库没有用户信息,那么调用三方接口去获取用户信息*/
            if(null == userCode){
                Map<String,Object> userParams = new HashMap<>();
                userParams.put("appKey","e74963fd39000fd695a1fa8f23ff9d8f");
                userParams.put("method","user.queryById");
                userParams.put("v","1.0");
                userParams.put("format", "json");
                userParams.put("id",easyOkHttpUtil.getUser());

                String sign = SignUtils.sign(userParams, "qljq");
                log.info("得到的sign值为: {}",sign);
                userParams.put("sign",sign);

                String data = bdpUtil.callGetString(RedirectUrl.LOGIN_URL_GETUSER, userParams);
                log.info("调用远程接口得到的json数据为: {}",data);

                //把当前的用户信息数据插入数据库在
                JSONObject jsonObject = JSONObject.parseObject(data);

                UserEntity userEntity = UserEntity.builder()
//                        .id(jsonObject.getString("userId"))
                        .username(jsonObject.getString("name"))
//                        .password(jsonObject.getString("password"))
                        .mobile(jsonObject.getString("phone"))
                        .email(jsonObject.getString("email"))
                        .gender(jsonObject.getString("sex"))
                        .dept(jsonObject.getString("teamName"))
//                        .deptId(jsonObject.getInteger("deptId"))
//                        .status(jsonObject.getBoolean("status"))
                        .url(jsonObject.getString("avatarImg"))
                        .idNumber(easyOkHttpUtil.getUser())
                        .build();

                userRepository.save(userEntity);
                log.info("数据插入成功");
            }



//userService.onePointLogin代码
  public String onePointLogin(String userId,String accessToken,Integer tokenTime) {
        /**
         *根据userId,查询当前用户是否存在。
         */
        log.info("要查询的userId为:" + userId);
        UserTmpEntity userEntity = userTmpRepository.findByIdNumber(userId);
        log.info("查询的结果为:" + userEntity);
        if(userEntity == null){
            return null;
        }

        //只要用户存在,就是登录成功
//        String random = userEntity.getUsername() + UuidUtil.random();

        loginService.cacheUserInfo2(accessToken,tokenTime, userEntity);
        return accessToken;
    }

B系统提供的进行用户登录的代码

获取到token和用户信息之后,我们就进行跳转到B系统的页面,因为当前登录页面是B系统提供的。

完整代码为:

    public ResultVo<String> onePointLogin(@RequestParam String code,
                                          HttpServletResponse response) throws IOException {
        if(code == null || "".equals(code)){
            log.info("没有获取到code,进行重定向获取code");
            try {
                response.sendRedirect(RedirectUrl.LOGIN_URL_NOCODE);
            }
            catch (Exception e){
                e.printStackTrace();
            }
            return ResultVo.ok("ok");
        }

        //如果有登录信息code,重定向获取accessToken.
        log.info("获取到code,进行重定向获取accessToken");
        try {
            Map<String,Object> params = new HashMap<>();
            EasyOkHttpUtil easyOkHttpUtil = bdpUtil.callGet(RedirectUrl.LOGIN_URL_CODE+code, params);
            log.info("调用三方接口返回的数据为: " +easyOkHttpUtil );

            //获取具体的返回参数
            log.info("得到的access_token为: "+easyOkHttpUtil.getAccess_token() + " expires_in: " + easyOkHttpUtil.getExpires_in());

            /**
             * 如果当前token已过期,则重新进行获取token
             */
            if(easyOkHttpUtil.getExpires_in() <=0){
                log.info("当前获得的token已过期,重新获取");
                try {
                    //因为这里我不知道code,所以重定向到了获取code的接口,按理说是直接重定向到获取token的接口。
                    response.sendRedirect(RedirectUrl.LOGIN_URL_NOCODE);
                }
                catch (Exception ex){
                    ex.printStackTrace();
                }
                ResultVo.ok("token已过期,重新获取token");
            }

            String userCode = userService.onePointLogin(easyOkHttpUtil.getUser(),easyOkHttpUtil.getAccess_token(),easyOkHttpUtil.getExpires_in());  //此时获取到的code是我们系统生成的token

            /**如果此时我们的数据库没有用户信息,那么调用三方接口去获取用户信息*/
            if(null == userCode){
                Map<String,Object> userParams = new HashMap<>();
                userParams.put("appKey","e74963fd39000fd695a1fa8f23ff9d8f");
                userParams.put("method","user.queryById");
                userParams.put("v","1.0");
                userParams.put("format", "json");
                userParams.put("id",easyOkHttpUtil.getUser());

                String sign = SignUtils.sign(userParams, "qljq");
                log.info("得到的sign值为: {}",sign);
                userParams.put("sign",sign);

                String data = bdpUtil.callGetString(RedirectUrl.LOGIN_URL_GETUSER, userParams);
                log.info("调用远程接口得到的json数据为: {}",data);

                //把当前的用户信息数据插入数据库在
                JSONObject jsonObject = JSONObject.parseObject(data);

                UserEntity userEntity = UserEntity.builder()
//                        .id(jsonObject.getString("userId"))
                        .username(jsonObject.getString("name"))
//                        .password(jsonObject.getString("password"))
                        .mobile(jsonObject.getString("phone"))
                        .email(jsonObject.getString("email"))
                        .gender(jsonObject.getString("sex"))
                        .dept(jsonObject.getString("teamName"))
//                        .deptId(jsonObject.getInteger("deptId"))
//                        .status(jsonObject.getBoolean("status"))
                        .url(jsonObject.getString("avatarImg"))
                        .idNumber(easyOkHttpUtil.getUser())
                        .build();

                userRepository.save(userEntity);
                log.info("数据插入成功");
            }
            //重新进行获取用户信息
            userCode = userService.onePointLogin(easyOkHttpUtil.getUser(),easyOkHttpUtil.getAccess_token(),easyOkHttpUtil.getExpires_in());
            if(null == userCode){
                try {
                    response.sendRedirect(RedirectUrl.LOGIN_URL_NOCODE);
                }
                catch (Exception e){
                    e.printStackTrace();
                }
                return ResultVo.ok("ok");
            }

            log.info("获取到用户信息的code为:" + userCode);
            Cookie cookie = new Cookie(Constant.HTTP_USER_HEADER, userCode);
            cookie.setMaxAge(easyOkHttpUtil.getExpires_in());
            response.addCookie(cookie);
            log.info("登录成功");
            response.sendRedirect("http://qzx.zh.sh/qljq/home");

//            response.sendRedirect(RedirectUrl.LOGIN_URL_CODE + code);
        }
        catch (Exception e){
            e.printStackTrace();
            response.sendRedirect(RedirectUrl.LOGIN_URL_NOCODE);
        }
        return ResultVo.ok("ok");
    }

在上面示例代码,通过传递过来的用户信息,和在A系统登录获得的token,和token的过期时间,进行在B系统用户的登录。

在B系统登录完成之后,重定向跳转到B系统的首页,进行操作B系统。

注意:在不同的系统之间,单点登录的系统使用同一个token,这个token是门户系统生成的,这样可能产生的影响为:不同的系统自己的操作,需要自己系统的token,而不需要门户的token。我之前遇到了这个问题,这个问题主要是通过拿到用户信息,进行模拟登录,来解决这个问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值