第三方系统单点登陆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(){//获取地址栏中的tokenvar 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*/@Autowiredprivate 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{@Autowiredprivate ISysUserService userService;@Autowiredprivate TokenService tokenService;@Resourceprivate AuthenticationManager authenticationManager;@Autowiredprivate 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.loadUserByUsernameUsernamePasswordAuthenticationToken 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());// 生成tokenreturn 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);@Autowiredprivate ISysUserService userService;@Autowiredprivate UserDetailsServiceImpl userDetailsService;@Autowiredprivate 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);}
}
总结
以上是实现第三方系统登陆若依系统的全部过程,这里不能叫做单点登陆,我称之为定向登陆,可能也不恰当,好用就行,有问题可以留言。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
