若依实现单点登录(解析请求链接中的参数做鉴权认证)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 若依实现单点登录(解析请求链接中的参数做鉴权认证)

实现思路


  1.    三方系统(也就是需要跳转我们系统的系统),直接请求我们系统的登录页面,挂着token参数。


  1.    在我们系统登录界面,判断请求链接中有没有token,没有则正常走登录流程。


  1.    如果没有token,则重新写一个单点登录的接口,去请求。


  1.    在后台将拿到的token,去三方系统中鉴权,通过则继续登录,没有通过则直接返回到登录页面。



实现代码


前端


1.在loginvue页面中的created方法中,调用单点登录的方法。

created() {
      //平台单独的登录  2022年4月19日11:23:58
      this.getLoginByNameAndTokenJ();
  },


2.在methods中写函数的实现:

  /**
     * 三方平台单点登陆系统 2022年4月19日11:22:33
     * 只传递token
     */
    getLoginByNameAndTokenJ(){
      //获取地址栏中的token
      var token = this.$route.query.token;
      //调用登录的接口
      if(token==''||token==undefined||token==null){
        //不是那边系统过来的,不走这个地方(阻止created的方法继续向下走)
      }else{
        //转圈圈,不要看到登陆页面,无感体验
        this.loading = true;
        var logininfo= {
          "token":token
        };
        //执行另一套登录操作
        //不是本系统的用户,去J平台登陆去
        this.$store.dispatch("LoginJHaveToken", logininfo).then(() => {
          this.$message.success("登录成功");
          this.loading = false;
          //判断当前角色
          getInfo().then((res) => {
            //获取角色名称
            var rolesName = res.roles[0];
            //获取所属场馆
            this.deptInfo = res.dept;
            sessionStorage.setItem("ssUserName", res.user.nickName);
            //如果是场馆管理员
            if (rolesName === 'changguanmanager') {
              this.$router.push({
                path: "/VenueKanban",
                query: {changguan: res, aa: 0},
                replace: true
              }).catch(() => {
              });
              //否则就是其他用户
            } else {
              this.$router.push({path: this.redirect || "/"}).catch(() => {
              });
            }
          });
        }).catch(err=> {
          console.log("有异常信息",err);
          //异常信息
          this.loading = false;
          if (this.captchaOnOff) {
            this.getCode();
          }
        });
      }
    },


3.在user.js中,实现LoginJHaveToken方法:

  //平台带着token登录,不需要输入账号密码
    //密码都是123456,
    //还需要带着token验证一下
    LoginJHaveToken({ commit }, userInfo) {
      const token = userInfo.token
      const queryParams ={
        'token':token
      };
      return new Promise((resolve, reject) => {
        getLoginByJHaveToken(queryParams).then(res => {
          setToken(res.token)
          commit('SET_TOKEN', res.token)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },


4.在login.js中,实现getLoginByJHaveToken方法:

  /**
   * 平台带着tonken进行登录
   *
   * @param queryParam
   * @returns {*}
   */
  export function getLoginByJHaveToken(queryParam) {
    return request({
      url: '/ToThirdPart/toThirdPartGetAuthJHaveToken',
      method: 'post',
      params: queryParam
    })
  }


后端


1.在/ToThirdPart/toThirdPartGetAuthJHaveToken控制器中实现登录的操作:

  /**
     * @Description: 平台带着token来系统里面登陆
     * 这边需要做两个步骤:
     * 1.检测数据库里面有没有这个用户名,有则不操作,无则添加
     * 2.去平台验证一下Token是否有,有的话继续操作后面的登录
     * 平台没有这个token,则直接打回去,不让上来
     * @author: 穆雄雄
     * @date: 2022/4/19 上午 11:38
     * @Return: com.ruoyi.common.core.domain.AjaxResult
     */
    @PostMapping("/toThirdPartGetAuthJHaveToken")
    @ApiOperation(value = "平台带着token过来登录")
    public AjaxResult toThirdPartGetAuthJHaveToken(String token) {
        //调用验证token的方法
        JSONObject jsonObject = checkJToken(token);
        String code = jsonObject.getString("code");
        Integer level = 0;
        String loginName = "";
        Long organId = null;
        //返回结果
        AjaxResult ajax = null;
        if (code.equals("0")) {
            //验证成功
            JSONObject dataObject = jsonObject.getJSONObject("data");
            //拿到其他的信息
            level = dataObject.getInteger("level");
            loginName = dataObject.getString("name");
            organId = dataObject.getLong("organId");
        } else {
            ajax = AjaxResult.error(jsonObject.getString("msg"));
            return ajax;
        }
        String isUserNameHas = "";
        //检测一下用户名存在不存在
        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(loginName))) {
            isUserNameHas = "用户已存在,不需要执行添加的操作";
        } else {
            //用户不存在时,将用户添加到数据库中
            SysUser sysUser = new SysUser();
            //登录名
            sysUser.setUserName(loginName);
            //昵称
            sysUser.setNickName(loginName);
            //密码统一都是123456
            sysUser.setPassword(SecurityUtils.encryptPassword("123456"));
            //创建者,标识J平台过来的用户
            sysUser.setCreateBy("j_have_token");
            //创建日期
            sysUser.setCreateTime(new Date());
            //所属等级
            sysUser.setHierarchy(level);
            //明文
            sysUser.setMingwen("123456");
            //账户权限:为了区分是平台的用户还是本系统用户
            //id返回来之后需要加上
            sysUser.setDeptId(organId);
            //所属等级如果没有,则角色是全国的
            //1  省  2 市     3  区
            if (level == null) {
                //角色
                Long[] roleids = {104L};
                sysUser.setRoleIds(roleids);
            } else {
                Long[] roleids = {100L};
                sysUser.setRoleIds(roleids);
            }
            int rows = userService.insertUser(sysUser);
            if (rows > 0) {
                isUserNameHas = "添加成功";
            }
        }
        ajax = AjaxResult.success();
        // 生成令牌(不加验证码登录)
        String tokenNew = loginService.loginNoCode(loginName, "123456", null);
        ajax.put(Constants.TOKEN, tokenNew);
        ajax.put("isUserNameHas", isUserNameHas);
        ajax.put("msg", "登录成功");
        return ajax;
    }


2.鉴权方法checkJToken,验证token是否存在,存在则返回用户信息,不存在则打回去:

   /**
     * 检测一下J平台的token 对不对
     *
     * @param token
     * @return
     */
    public JSONObject checkJToken(String token) {
        JSONObject jsonObject = new JSONObject();
        //测试环境
        String baseUrl = "http://xxxxx/checkTokenRtnInfo?stk=" + token;
        HttpResponse d = HttpRequest.get(baseUrl)
                .header(HttpHeaders.CONTENT_TYPE, "application/json")
                .header(HttpHeaders.ACCEPT, "application/json")
                .execute();
        return (JSONObject) JSONObject.parse(d.body().toString());
    }


3.绕过验证码登录的方法,重写loginService.loginNoCode方法:

    /**
     * 不加验证码登录
     *
     * @param username 用户名
     * @param password 密码
     * @param uuid 唯一标识
     * @return 结果
     */
    public String loginNoCode(String username, String password,  String uuid)
    {
        // 用户验证
        Authentication authentication = null;
        try
        {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(username, password));
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        return tokenService.createToken(loginUser);
    }


最后就可以了,可能这种方式不是最好的,但是目前仅想到这种方法。




注意事项


  1. 因为若依的登录方法是带着验证码的,如果不带,则会提示验证码失效


  1. 目前登录传参的方式是post,相对比较安全点。


  1. 三方系统请求的时候,参数是在链接中挂着,不是很靠谱。
目录
相关文章
|
4月前
|
缓存 前端开发 中间件
[go 面试] 前端请求到后端API的中间件流程解析
[go 面试] 前端请求到后端API的中间件流程解析
|
2月前
|
前端开发 JavaScript UED
axios取消请求CancelToken的原理解析及用法示例
axios取消请求CancelToken的原理解析及用法示例
118 0
|
3月前
|
JSON API 数据格式
requests库中json参数与data参数使用方法的深入解析
选择 `data`或 `json`取决于你的具体需求,以及服务器端期望接收的数据格式。
240 2
|
2月前
|
存储 缓存 并行计算
yolov5的train.py的参数信息解析
这篇文章解析了YOLOv5的`train.py`脚本中的参数信息,详细介绍了每个参数的功能和默认值,包括权重路径、模型配置、数据源、超参数、训练轮数、批量大小、图像尺寸、训练选项、设备选择、优化器设置等,以便用户可以根据需要自定义训练过程。
35 0
|
4月前
|
数据采集
深度解析CancellationToken在HttpClient请求中的应用
本文讨论了在.NET环境中使用HttpClient进行爬虫开发时,如何应用CancellationToken来控制请求的生命周期,提高爬虫的效率和稳定性。通过结合爬虫代理IP技术、多线程请求、设置User-Agent和Cookie等策略,可以增强爬虫的灵活性并降低被网站封禁的风险。文章提供了一个使用CancellationToken和代理IP的多线程爬虫实现示例代码,并详细解析了代码的关键部分,包括CancellationToken的使用、代理IP的配置、并发请求的实现以及User-Agent和Cookie的设置。
深度解析CancellationToken在HttpClient请求中的应用
|
3月前
|
存储 JSON API
Python编程:解析HTTP请求返回的JSON数据
使用Python处理HTTP请求和解析JSON数据既直接又高效。`requests`库的简洁性和强大功能使得发送请求、接收和解析响应变得异常简单。以上步骤和示例提供了一个基础的框架,可以根据你的具体需求进行调整和扩展。通过合适的异常处理,你的代码将更加健壮和可靠,为用户提供更加流畅的体验。
181 0
|
4月前
|
开发者 Python
深入解析Python `requests`库源码,揭开HTTP请求的神秘面纱!
深入解析Python `requests`库源码,揭开HTTP请求的神秘面纱!
185 1
|
4月前
|
C# 开发者 Windows
震撼发布:全面解析WPF中的打印功能——从基础设置到高级定制,带你一步步实现直接打印文档的完整流程,让你的WPF应用程序瞬间升级,掌握这一技能,轻松应对各种打印需求,彻底告别打印难题!
【8月更文挑战第31天】打印功能在许多WPF应用中不可或缺,尤其在需要生成纸质文档时。WPF提供了强大的打印支持,通过`PrintDialog`等类简化了打印集成。本文将详细介绍如何在WPF应用中实现直接打印文档的功能,并通过具体示例代码展示其实现过程。
347 0
|
4月前
|
存储 Go UED
精通Go语言的命令行参数解析
【8月更文挑战第31天】
49 0

推荐镜像

更多