因业务需求,需要从第三方系统跳转到若依开发的系统中,跳转后无需输入用户名、密码、验证码自动登陆,没有权限则提示您无权登陆,请联系管理员。
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);
}
}
以上是实现第三方系统登陆若依系统的全部过程,这里不能叫做单点登陆,我称之为定向登陆,可能也不恰当,好用就行,有问题可以留言。