实现思路
- 三方系统(也就是需要跳转我们系统的系统),直接请求我们系统的登录页面,挂着token参数。
- 在我们系统登录界面,判断请求链接中有没有token,没有则正常走登录流程。
- 如果没有token,则重新写一个单点登录的接口,去请求。
- 在后台将拿到的token,去三方系统中鉴权,通过则继续登录,没有通过则直接返回到登录页面。
实现代码
前端
1.在login
的vue
页面中的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); }
最后就可以了,可能这种方式不是最好的,但是目前仅想到这种方法。
注意事项
- 因为若依的登录方法是带着验证码的,如果不带,则会提示验证码失效
- 目前登录传参的方式是
post
,相对比较安全点。
- 三方系统请求的时候,参数是在链接中挂着,不是很靠谱。