第三方系统单点登陆RuoYi-Vue系统


说明

因业务需求,需要从第三方系统跳转到若依开发的系统中,跳转后无需输入用户名、密码、验证码自动登陆,没有权限则提示您无权登陆,请联系管理员。


一、实现思路

1、第三方跳转新开发的系统中带着token请求参数
2、验证token及用户权限,有权限直接跳转登陆,否则提示无权限不进行跳转

二、实现代码

前端

1、在view目录下新建thirdPlatLogin.vue文件,具体代码如下:

<template>
  <div></div>
</template>

<script>
export default {
  name: "Login",
  data() {
    return {

      loginRules: {

      },
      loading: false,
      // 验证码开关
      captchaOnOff: true,
      // 注册开关
      register: false,
      redirect: undefined
    };
  },
  watch: {
    $route: {
      handler: function(route) {
        console.log("路由:"+route)
        this.redirect = route.query && route.query.redirect;
      },
      immediate: true
    }
  },
  created() {
    //平台单独的登录
    this.getLoginByNameAndTokenJ();
  },
  methods: {
    /**
     * 三方平台单点登陆
     * 只传递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;
          this.$router.push({path: this.redirect || "/"}).catch(() => {});
        }).catch(err=> {
          console.log("有异常信息",err);
          //异常信息
          this.loading = false;
        });
      }
    },
  }
};
</script>
<style rel="stylesheet/scss" lang="scss">

</style>

2.在store->modules的user.js中,实现LoginJHaveToken方法

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)
        })
      })
    },

3、在api目录的login.js中,实现getLoginByJHaveToken方法:

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

4、在router的index.js中的公共路由变量constantRoutes,添加如下路由:

{
    path: '/thirdPlatLogin',
    component: () => import('@/views/thirdPlatLogin'),
    hidden: true
  }

5、在src的permission.js中,修改白名单如下:

修改前
const whiteList = ['/login', '/register']
修改后
const whiteList = ['/login', '/register', '/thirdPlatlogin']

后端

1、在ruoyi-admin模块的web-controller-system下新建ThirdPartLoginController文件,代码如下:

package com.ruoyi.web.controller.system;

/**
 * @projectName: RuoYi-Vue
 * @package: com.ruoyi.web.controller.system
 * @className: ThirdPartLoginController
 * @author: sean
 * @description: TODO
 * @date: 2023/2/20 14:47
 * @version: 1.0
 */

import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.web.service.ThirdLoginService;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 第三方登录验证
 *
 * @author ruoyi
 */
@RestController
public class ThirdPartLoginController {
    /**
     * @Description: 平台带着token来系统里面登陆
     * 这边需要做两个步骤:
     * 1.检测数据库里面有没有这个用户名,没有提示用户不存在
     * 2.有则执行登陆操作
     * 平台没有这个token,则直接打回去,不让上来
     * @author: sean
     * @date: 2023/2/21 17:40
     * @version: 1.0
     */
    @Autowired
    private ThirdLoginService loginService;

    @Anonymous
    @PostMapping("/toThirdPartGetAuthJHaveToken")
    @ApiOperation(value = "平台带着token过来登录")
    public AjaxResult toThirdPartGetAuthJHaveToken(String token) {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌(免密登录)
        String tokenNew = loginService.thirdLogin(token);
        ajax.put(Constants.TOKEN, tokenNew);
        ajax.put("msg", "登录成功");
        return ajax;
    }
}

2、在ruoyi-framework模块的web-service创建ThirdLoginService服务类,实际业务中使用的是thirdLogin方法,代码如下:

package com.ruoyi.framework.web.service;

import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Optional;

/**
 * @projectName: RuoYi-Vue
 * @package: com.ruoyi.framework.web.service
 * @className: ThirdLoginService
 * @author: sean
 * @description: TODO
 * @date: 2023/2/22 7:53
 * @version: 1.0
 */
@Service
public class ThirdLoginService{

    @Autowired
    private ISysUserService userService;

    @Autowired
    private TokenService tokenService;

    @Resource
    private AuthenticationManager authenticationManager;
    @Autowired
    private ThirdUserDetailsService userDetailsService;

    /**
     * 无密码登录
     * @param userName
     * @return
     * @author sean
     * @date 2023/2/21 17:52
     */
    public String noPwdLogin(String userName){
        LoginUser loginUser
                = (LoginUser)userDetailsService.loadUserByUsername(userName);
        // 记录登陆信息
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGIN_SUCCESS,
                MessageUtils.message("user.login.success")));
        recordLoginInfo(loginUser.getUserId());
        return tokenService.createToken(loginUser);
    }

    /**
     * 不加验证码登录
     *
     * @param username 用户名
     * @param password 密码
     * @param uuid 唯一标识
     * @return 结果
     * @author sean
     * @date 2023/2/21 17:52
     */
    public String loginNoCode(String username, String password,  String uuid)
    {
        // 用户验证
        Authentication authentication = null;
        try
        {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
            AuthenticationContextHolder.setContext(authenticationToken);
            authentication = authenticationManager.authenticate(authenticationToken);
        }
        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);
    }

    /**
     * @param token:
     * @return String
     * @title thirdLogin
     * @descriptions 三方平台登陆
     * @author sean
     * @date 2023/2/21 17:52
     */
    public String thirdLogin(String token){
        //根据token获取用户相关信息
        SysUser sysUser = userService.getUserByToken(token);
        Optional.ofNullable(sysUser).orElseThrow(
                ()->new ServiceException("用户不存在,请联系管理员"));
        return this.noPwdLogin(sysUser.getUserName());
    }


    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        sysUser.setLoginDate(DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);
    }
}

ThirdUserDetailsService类文件代码如下:

package com.ruoyi.framework.web.service;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

/**
 * @projectName: RuoYi-Vue
 * @package: com.ruoyi.framework.web.service
 * @className: ThirdUserDetailsService
 * @author: sean
 * @description: TODO
 * @date: 2023/2/22 8:26
 * @version: 1.0
 */
@Service
public class ThirdUserDetailsService{

    private static final Logger log = LoggerFactory.getLogger(ThirdUserDetailsService.class);

    @Autowired
    private ISysUserService userService;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private SysPasswordService passwordService;
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
    {
        SysUser user = userService.selectUserByUserName(username);
        if (StringUtils.isNull(user))
        {
            log.info("登录用户:{} 不存在.", username);
            throw new ServiceException("登录用户:" + username + " 不存在");
        }
        else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
        {
            log.info("登录用户:{} 已被删除.", username);
            throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
        }
        else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
        {
            log.info("登录用户:{} 已被停用.", username);
            throw new ServiceException("对不起,您的账号:" + username + " 已停用");
        }

        passwordService.clearLoginRecordCache(username);

        return userDetailsService.createLoginUser(user);
    }
}


总结

以上是实现第三方系统登陆若依系统的全部过程,这里不能叫做单点登陆,我称之为定向登陆,可能也不恰当,好用就行,有问题可以留言。

  • 8
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
### 回答1: ruoyi-vue-oracle是一种基于vue.js开发的前端框架,它使用了Oracle数据库作为后端的数据存储和处理工具。ruoyi-vue是一个开源的管理系统框架,它结合了vue.js和element-ui,提供了丰富的组件和插件,帮助开发者快速构建现代化的管理系统。而Oracle是一种强大的关系型数据库管理系统,它具有高性能、高可靠性和安全性的特点,被广泛应用于企业级应用程序。 通过ruoyi-vue-oracle,开发者可以轻松地搭建一个功能强大、稳定可靠的管理系统。vue.js作为前端框架,提供了灵活且高效的开发方式,可以实现各种交互效果和页面布局;element-ui则为开发者提供了丰富的组件和样式,极大地提高了开发效率。而Oracle数据库作为后端存储工具,可以处理大量数据并保证数据的一致性和安全性。 ruoyi-vue-oracle还可以实现用户权限管理、数据管理和系统监控等功能。用户权限管理可以根据角色和权限划分用户的访问权限,确保系统的安全性;数据管理可以对数据库进行增删改查操作,满足对数据的管理需求;系统监控可以实时监控系统的运行状态和性能,及时发现并解决问题。 总之,ruoyi-vue-oracle提供了一套完整的开发框架和解决方案,帮助开发者快速构建现代化的管理系统。无论是企业级应用还是个人项目,都可以通过ruoyi-vue-oracle实现快速、稳定的开发。 ### 回答2: ruoyi-vue-oracle是一个开源的后台管理系统,采用了前后端分离的架构,前端使用了Vue.js框架,后端使用了Spring Boot框架,数据库使用了Oracle。这个系统提供了丰富的功能,包括用户管理、角色管理、菜单管理、部门管理、字典管理、通知公告管理等。 在前端方面,ruoyi-vue使用了Vue.js来构建用户界面,提供了响应式的布局和丰富的组件,使得用户可以方便地进行操作和管理。同时,Vue.js也提供了一套模块化的开发方式,使得项目的代码结构清晰、可维护性高。 在后端方面,ruoyi-vue使用了Spring Boot作为基础框架,结合了Spring框架的优点,提供了一套强大的开发工具和生命周期管理,简化了开发流程并提高了生产力。同时,Spring Boot还集成了许多常用的功能和组件,如安全认证、缓存、数据库等,这些都可以帮助开发者快速搭建稳定可靠的系统。 数据库方面,ruoyi-vue选择了Oracle作为后端的数据库,Oracle是目前业界广泛使用的关系型数据库之一,具有强大的存储和查询能力,可以满足大部分企业级应用的需求。在ruoyi-vue中,通过使用数据库的事务管理,保证了数据的一致性和完整性。 总体来说,ruoyi-vue-oracle是一个功能强大且易于使用的后台管理系统,它提供了丰富的功能和灵活的架构,能够帮助开发者快速构建高效稳定的系统。 ### 回答3: ruoyi-vue-oracle是一个基于Vue.js和Spring Boot的开源框架,用于快速构建前后端分离的管理系统。Oracle是一种关系型数据库管理系统,用于存储和管理大量结构化数据。 ruoyi-vue-oracle提供了一套完整的解决方案,包括前端页面、后端接口和数据库模型。前端页面采用Vue.js框架编写,具有良好的用户交互体验和响应速度。后端接口基于Spring Boot框架开发,提供了丰富的业务功能和数据处理能力。Oracle数据库作为数据存储介质,提供了高性能、高可用性和数据安全性,适用于处理大规模数据和复杂查询。 使用ruoyi-vue-oracle框架,开发人员可以快速搭建管理系统,并轻松实现用户管理、角色权限、数据字典、系统监控、日志管理等常见功能。同时,该框架还提供了丰富的扩展和定制功能,便于根据项目需求进行二次开发。 总之,ruoyi-vue-oracle是一个功能强大的前后端分离框架,可以帮助开发人员快速构建高效、稳定的管理系统。Oracle数据库作为数据存储的选择,能够提供可靠的数据管理与查询服务。结合两者,可以满足企业对高性能、可扩展性和良好用户体验的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值