ruoyi-vue前后端分离实现统一登录认证登录

 1、功能描述

本系统作为其他系统的子系统,不使用自己的登录页面,从统一平台跳转到本平台。所以本平台需要作为子系统进行统一认证登录。

功能:1.从统一平台使用携带认证票据的链接进入本系统;

      2.定时校验认证是否过期;

      3.上述两个失败后均跳转到特定网址;

参考网址:

https://blog.csdn.net/csdn_avatar_2019/article/details/129306927

2、前端

2.1 新增login_sso.vue

/src/view/下新增login_sso.vue文件作为自动登录的前端入口.





2.2 index.js注册路由

ruoyi-vue前后端分离实现统一登录认证登录_第1张图片

2.3 permission.js增加白名单过滤

2.4 login.js增加后端登录接口​​​​

//单点登录 无验证码登录
export function loginSso(queryParam) {
  return request({
    url: '/loginSso',
    method: 'post',
    params: queryParam
  })
}

//登录状态校验
export function checkTicket(queryParam) {
  return request({
    url: '/checkTicket',
    method: 'post',
    params: queryParam
  })
}

 2.5/src/store/modules/user.js增加单点登录方法

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

//……
}

 3、后端改造

 ​​3.1​引入依赖

在admin模块下的pom.xml中引入



    org.jodd
    jodd-http
    6.3.0

 3.2 ​​新增LoginSsoController单点登录控制器

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;
    }
}

3.3 增加单点登录后端方法

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

 ​​​3.4 增加shiro白名单

增加后端对于/loginSso的放行.

你可能感兴趣的:(vue.js,前端,javascript)