本系统作为其他系统的子系统,不使用自己的登录页面,从统一平台跳转到本平台。所以本平台需要作为子系统进行统一认证登录。
功能:1.从统一平台使用携带认证票据的链接进入本系统;
2.定时校验认证是否过期;
3.上述两个失败后均跳转到特定网址;
参考网址:
https://blog.csdn.net/csdn_avatar_2019/article/details/129306927
在/src/view/下新增login_sso.vue文件作为自动登录的前端入口.
//单点登录 无验证码登录
export function loginSso(queryParam) {
return request({
url: '/loginSso',
method: 'post',
params: queryParam
})
}
//登录状态校验
export function checkTicket(queryParam) {
return request({
url: '/checkTicket',
method: 'post',
params: queryParam
})
}
import { login, logout, getInfo, loginSso } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
actions: {
//……
//单点登录
LoginSso({commit}, userInfo){
const ticket = userInfo.ticket;
const queryParams = {
'ticket' : ticket
};
return new Promise((resolve, reject) => {
loginSso(queryParams).then(res => {
setToken(res.token)
commit('SET_TOKEN', res.token)
resolve()
}).catch(error => {
reject(error)
})
})
},
//……
}
在admin模块下的pom.xml中引入
org.jodd
jodd-http
6.3.0
package com.ruoyi.web.controller.system;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 单点登录Controller
* @author sgc
*/
@RestController
public class LoginSsoController {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
private final String url = "http://xxx";//验证请求地址
@Autowired
private ISysUserService userService;
@Autowired
private SysLoginService loginService;
@PostMapping("/loginSso")
public AjaxResult loginSso(String ticket) {
AjaxResult ajax = new AjaxResult();
//这里进行单点登录上级系统的令牌校验 写自己的逻辑
JSONObject ssoObject = getRequst(url+"xxx?ticket=" + ticket) ;
//处理结果 {code=xxx,result={xxx},msg=xxx}
Integer code = ssoObject.getInteger("code");
if(code != 200 && code != 0){
ajax.put("code", code);
ajax.put("msg",ssoObject.getString("msg"));
return ajax;
}
JSONObject result = ssoObject.getJSONObject("result");//用户信息
if(!result.containsKey("userName") || result.getString("userName").isEmpty()){
ajax.put("code", 204);
ajax.put("msg","用户名称返回为空");
return ajax;
}
String userName= result.getString("userName");
//验证的逻辑根据实际填写 if(userService.checkUserExist(userName)){
//生成本系统的令牌给到前端进行登录
ajax = AjaxResult.success();
//这里设置单点登录用户默认密码为123456
String tokenNew = loginService.loginNoCaptcha(realName, "123456", null);
ajax.put("token", tokenNew);
ajax.put("msg", "登录成功");
ajax.put("ticket",ticket);
return ajax;
}else{
ajax.put("code", 403);
ajax.put("msg","用户不存在");
return ajax;
}
}
/**
* 发送get请求,返回结果json
* @param baseUrl 请求路径,带参数
* @return
*/
private JSONObject getRequst(String baseUrl){
JSONObject jsonObject = new JSONObject();
String resStr = HttpUtils.sendGet(baseUrl);
System.out.println(resStr);
//处理回复
if(resStr.contains("code")) {
JSONObject jsonObjectRes = JSON.parseObject(resStr);
Integer code = jsonObjectRes.getInteger("code");
String message = jsonObjectRes.getString("message");
JSONObject result = jsonObjectRes.getJSONObject("result");
jsonObject.put("code",code);
jsonObject.put("msg",message);
jsonObject.put("result",result);
}else{
jsonObject.put("code",204);
jsonObject.put("msg","请求回复内容为空");
}
return jsonObject;
}
//登录状态校验
@PostMapping("/checkTicket")
public AjaxResult checkTicket(String ticket) {
AjaxResult ajax = new AjaxResult();
JSONObject jsonObjectRes = getRequst(url+"xxx?ticket=" + ticket);
Integer code = jsonObjectRes.getInteger("code");
if (code != 200 && code != 0) {
ajax.put("code", code);
ajax.put("msg", jsonObjectRes.getString("msg"));
return ajax;
}
//处理回复
JSONObject result = jsonObjectRes.getJSONObject("result");//用户信息
if (!result.containsKey("tokenState") ) {
ajax.put("code", 204);
ajax.put("msg", "请求回复不包含tokenState");
}
if (!result.getBoolean("tokenState")) {
ajax.put("code", 403);
ajax.put("msg", "用户登录失效");
}
ajax.put("code", 200);
ajax.put("msg", "登录状态校验通过");
return ajax;
}
}
在com.ruoyi.framework.web.service.SysLoginService中增加一个无验证码登录的方法loginNoCaptcha.
/**
* 无需验证码登录
* 重写login方法将验证码模块去掉
* @param username
* @param password
* @param uuid
* @return
*/
public String loginNoCaptcha(String username, String password, String uuid)
{
// 用户验证
Authentication authentication = null;
try
{
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
AuthenticationContextHolder.setContext(authenticationToken);
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
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);
}
增加后端对于/loginSso的放行.