大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂
前言
现在是:2022年4月19日19:56:56
昨天写了个bladex
的单点登录,回想起来还是比较复杂的,今天又收到了个在若依
里面实现单点登录。具体是这样的:别的系统中访问我们的系统,但是用户已经在那边系统登录过了,跳转到这边无需在来一次登录,直接上本系统中继续后续的操作。
实现思路
- 三方系统(也就是需要跳转我们系统的系统),直接请求我们系统的登录页面,挂着
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
,相对比较安全点。 - 三方系统请求的时候,参数是在链接中挂着,不是很靠谱。
相关文章
暂无评论...