若依实现系统单点登录(可绕过验证码)

简介: 若依实现系统单点登录(可绕过验证码)


前言

现在是:2022年4月19日19:56:56

昨天写了个bladex的单点登录,回想起来还是比较复杂的,今天又收到了个在若依里面实现单点登录。具体是这样的:别的系统中访问我们的系统,但是用户已经在那边系统登录过了,跳转到这边无需在来一次登录,直接上本系统中继续后续的操作。

实现思路

  1. 三方系统(也就是需要跳转我们系统的系统),直接请求我们系统的登录页面,挂着token参数。
  2. 在我们系统登录界面,判断请求链接中有没有token,没有则正常走登录流程。
  3. 如果没有token,则重新写一个单点登录的接口,去请求。
  4. 在后台将拿到的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. 因为若依的登录方法是带着验证码的,如果不带,则会提示验证码失效
  2. 目前登录传参的方式是post,相对比较安全点。
  3. 三方系统请求的时候,参数是在链接中挂着,不是很靠谱。
目录
相关文章
|
8天前
|
JSON 缓存 JavaScript
❤Nodejs 第十章(用户信息token认证和登录接口开发)
【4月更文挑战第10天】本文介绍了Node.js中实现用户信息token认证和登录接口的步骤。express-jwt的使用,接着创建基本的Express服务器,然后导入并使用jsonwebtoken和express-jwt。设置一个密钥,并定义一个中间件处理token验证。示例展示了登录接口的实现。遇到登录判断失效的问题后,对判断条件进行了优化。
27 2
|
4月前
|
存储 JSON JavaScript
前后端分离项目知识汇总(微信扫码登录,手机验证码登录,JWT)-1
前后端分离项目知识汇总(微信扫码登录,手机验证码登录,JWT)
67 0
|
8月前
JavaWeb用户信息管理系统-在登录中添加验证码功能
JavaWeb用户信息管理系统-在登录中添加验证码功能
47 0
|
5天前
|
存储 前端开发 JavaScript
前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
23 1
|
3月前
|
存储 缓存
实现单点登录的方式
实现单点登录的方式
31 1
|
4月前
|
JSON 前端开发 安全
前后端分离项目知识汇总(微信扫码登录,手机验证码登录,JWT)-2
前后端分离项目知识汇总(微信扫码登录,手机验证码登录,JWT)
58 0
|
4月前
|
小程序 数据安全/隐私保护 C++
一个简便的第三方授权登录
一个简便的第三方授权登录
|
安全 网络安全 数据安全/隐私保护
Jasny SSO是如何处理安全性问题的?底层原理是什么?
Jasny SSO是如何处理安全性问题的?底层原理是什么?
|
数据安全/隐私保护
Jasny SSO支持哪些认证方式?底层原理是什么?
Jasny SSO支持哪些认证方式?底层原理是什么?
|
JavaScript 中间件 数据安全/隐私保护
【每日渗透笔记】后台弱口令+未授权尝试
【每日渗透笔记】后台弱口令+未授权尝试
159 0
【每日渗透笔记】后台弱口令+未授权尝试