springboot实现用户统一认证、管理

举报
穆雄雄 发表于 2022/12/06 20:22:38 2022/12/06
【摘要】 大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂 前言现在是:2022年5月25日13:44:16最近和模拟登录杠上了,这不,又来了个需求,还是以这个技术点入手的。需求大概是这样的:为了统一管理系统的用户,上游平台做了个统一认证平台,所有用户进入子系统只有一个入口,即:上游平台登录入口,新用户也是上游平台进行添加;子系统的用户登录和注册模块都屏蔽掉。 设计技能点前端:Vue后端:sprin...

大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂

前言

现在是:2022年5月25日13:44:16

最近和模拟登录杠上了,这不,又来了个需求,还是以这个技术点入手的。需求大概是这样的:为了统一管理系统的用户,上游平台做了个统一认证平台,所有用户进入子系统只有一个入口,即:上游平台登录入口,新用户也是上游平台进行添加;子系统的用户登录和注册模块都屏蔽掉。

设计技能点

  1. 前端:Vue
  2. 后端:springboot (bladex框架)
  3. 数据库:mysql 5.7及以上

实现思路

  1. 上游平台通过回调接口,将用户和组织机构同步至子系统
  2. 上游平台通过url在地址栏中挂sessionid的方式访问子系统的登录页面
  3. 子系统检地址栏中是否有sessionid,如果有,则拿着sessionid去上游系统获取用户信息,然后在子系统中拿着用户信息自动登录
  4. 如果地址栏中没有sessionid,则需要带着子系统的登录地址,重定向至上游平台(上游平台怎么处理的,我就不知道了,我猜测,如果用户未在上游平台登录,则不带sessionid来的子系统,如果登录了则会带着过来。所以重定向到上游平台时,应该是让用户重新进行登录的)
  5. 当用户点击退出时,清除子系统的用户登录状态的同时还需要清除上游系统,且重定向至上游平台的登录页面

代码实现

回调接口实现了两个功能:

  • 同步组织机构
  • 同步用户信息

为了后期维护方便,前后端所有调用外部的地址,从接口中获取数据等均单独提取出来了,这样也能更好的实现复用。

  1. 统一接口管理SsoLoginConstant
package org.springblade.modules.system.util;

 /**
 * @Description: TODO
 * @author: 穆雄雄
 * @date: 2022/5/17 下午 2:40
  * 放一些公共的常量
 * @Return:
 */
 public interface SsoLoginConstant {

  /**
   * 统一认证平台的地址
   */
  public final static String SSO_URL = "http://************";


  /**
   * 登录鉴权
   */

  public final static  String CHECKLOGIN_URL =SSO_URL+ "/check_login";

  /**
   * 查询平台用户信息
   */
  public final static  String QUERYUSER_URL =SSO_URL+ "/get_user";

  /**
   * 查询平台组织机构信息
   */
  public final static String QUERYDEPARTMENT_URL =SSO_URL+ "/get_department";

  /**
   * 退出系统
   */
  public final static String APILOGOUT_URL =SSO_URL+ "/api_logout";


 }

  1. 公用Service层接口:
package org.springblade.modules.system.service;

 import org.springblade.core.tool.api.R;
 import org.springframework.web.bind.annotation.RequestBody;

 /**
  * @author: muxiongxiong
  * @date: 2022年05月21日 上午 8:41
  * 公众号:雄雄的小课堂
  * 博客:https://blog.csdn.net/qq_34137397
  * 个人站:http://www.穆雄雄.com
  * 个人站:http://www.muxiongxiong.cn
  * @Description: 类的描述:单点登录业务层接口
  */
 public interface ISsoLoginService {

  /**
  * @Description: 登录鉴权
  * @author: 穆雄雄
  * @date: 2022/5/21 上午 8:54
  No such property: code for class: Script1
  * @Return:
  */
  String checkLogin(String ssoSessionKey);

  /**
   * @Description: 查询平台用户信息
   * @author: 穆雄雄
   * @date: 2022/5/21 上午 8:42
   * 查询平台用户信息
   * @Return:
   */
  String getUser(String projectKey);

  /**
  * @Description: 查询平台组织机构信息
  * @author: 穆雄雄
  * @date: 2022/5/21 上午 8:50
  * 查询平台用户信息
  * @Return: java.lang.String
  */
  String getDepartment(String projectKey);

  /**
  * @Description: 上传平台用户信息
  * @author: 穆雄雄
  * @date: 2022/5/21 上午 9:24
  * @Return: java.lang.String
  */
  R pullUserInfo(@RequestBody String val);

  /**
   * @Description: 退出
   * @author: 穆雄雄
   * @date: 2022年5月25日15:34:58
  No such property: code for class: Script1
   * @Return:
   */
  String apiLogout(String ssoSessionKey);

 }

  1. Service层实现类:
package org.springblade.modules.system.service.impl;

 import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.commons.lang.StringUtils;
 import org.springblade.core.tool.api.R;
 import org.springblade.modules.system.entity.Dept;
 import org.springblade.modules.system.entity.User;
 import org.springblade.modules.system.entity.UserService;
 import org.springblade.modules.system.service.IDeptService;
 import org.springblade.modules.system.service.ISsoLoginService;
 import org.springblade.modules.system.service.IUserService;
 import org.springblade.modules.system.util.SsoLoginConstant;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;

 import java.util.HashMap;
 import java.util.Map;

 /**
  * @author: muxiongxiong
  * @date: 2022年05月21日 上午 8:51
  * 公众号:雄雄的小课堂
  * 博客:https://blog.csdn.net/qq_34137397
  * 个人站:http://www.穆雄雄.com
  * 个人站:http://www.muxiongxiong.cn
  * @Description: 类的描述
  */
 @Service
 public class SsoLoginServiceImpl implements ISsoLoginService {

  @Autowired
  private IUserService userService;

  @Autowired
  private IDeptService deptService;


  /**
   * 登录鉴权
   */
  @Override
  public String checkLogin(String ssoSessionKey) {
   JSONObject jsonObjectResult = new JSONObject();
   //请求接口地址
   String url = SsoLoginConstant.CHECKLOGIN_URL;
   Map<String, Object> paramMap = new HashMap<String, Object>();
   paramMap.put("ssoSessionKey", ssoSessionKey);
   try {
    String body = HttpUtil.createPost(url).form(paramMap).execute().body();
    if (StringUtils.isBlank(body)) {
     jsonObjectResult.put("code", 500);
     jsonObjectResult.put("msg", "请求失败");
     jsonObjectResult.put("data", "");
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
    JSONObject obj = JSONObject.parseObject(body);
    if (obj == null) {
     jsonObjectResult.put("code", 500);
     jsonObjectResult.put("msg", "请求失败");
     jsonObjectResult.put("data", "");
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
    String code = obj.get("code").toString();
    if ("200".equals(code)) {
     jsonObjectResult.put("code", 200);
     jsonObjectResult.put("msg", "请求成功");
     jsonObjectResult.put("data", obj.get("data"));
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }else{
     jsonObjectResult.put("code", 500);
     jsonObjectResult.put("msg", "请求失败");
     jsonObjectResult.put("data", "");
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
   return jsonObjectResult.toJSONString();
  }

  /**
   * 获取平台用户
   */
  @Override
  public String getUser(String projectKey) {
   JSONObject jsonObjectResult = new JSONObject();
   //请求接口地址
   String url = SsoLoginConstant.QUERYUSER_URL;
   Map<String, Object> paramMap = new HashMap<String, Object>();
   paramMap.put("projectKey", projectKey);
   try {
    String body = HttpUtil.createGet(url).form(paramMap).execute().body();
    if (StringUtils.isBlank(body)) {
     jsonObjectResult.put("code", 500);
     jsonObjectResult.put("msg", "请求失败");
     jsonObjectResult.put("data", "");
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
    JSONObject obj = JSONObject.parseObject(body);
    if (obj == null) {
     jsonObjectResult.put("code", 500);
     jsonObjectResult.put("msg", "请求失败");
     jsonObjectResult.put("data", "");
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
    String code = obj.get("code").toString();
    if ("200".equals(code)) {
     jsonObjectResult.put("code", 200);
     jsonObjectResult.put("msg", "请求成功");
     jsonObjectResult.put("data", obj.get("data"));
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
   return jsonObjectResult.toJSONString();
  }

  /**
   * 获取组织机构
   */
  @Override
  public String getDepartment(String projectKey) {
   JSONObject jsonObjectResult = new JSONObject();
   //请求接口地址
   String url = SsoLoginConstant.QUERYDEPARTMENT_URL;
   Map<String, Object> paramMap = new HashMap<String, Object>();
   paramMap.put("projectKey", projectKey);
   try {
    String body = HttpUtil.createGet(url).form(paramMap).execute().body();
    if (StringUtils.isBlank(body)) {
     jsonObjectResult.put("code", 500);
     jsonObjectResult.put("msg", "请求失败");
     jsonObjectResult.put("data", "");
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
    JSONObject obj = JSONObject.parseObject(body);
    if (obj == null) {
     jsonObjectResult.put("code", 500);
     jsonObjectResult.put("msg", "请求失败");
     jsonObjectResult.put("data", "");
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
    String code = obj.get("code").toString();
    if ("200".equals(code)) {
     jsonObjectResult.put("code", 200);
     jsonObjectResult.put("msg", "请求成功");
     jsonObjectResult.put("data", obj.get("data"));
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
   return jsonObjectResult.toJSONString();
  }

  /**
   * 上传平台用户信息
   * @param val
   * @return
   */
  @Override
  public R pullUserInfo(String val) {
   //转换成集合类型
   JSONArray userListArray = JSONArray.parseArray(val);
   boolean flag = false;
   for (Object o : userListArray) {
    JSONObject jsonObject = (JSONObject) o;
    User user = new User();
    //add表示添加
    //update表示更新
    //delete表示删除
    String operate = jsonObject.getString("operate");
    //固定标识
    String type = jsonObject.getString("type");
    JSONObject dataObject = jsonObject.getJSONObject("data");
    if (type.equals("sso_user")) {
     Long id = dataObject.getLong("id");
     //用户账号
     String account = dataObject.getString("account");
     //用户名称
     String name = dataObject.getString("name");
     //所属部门
     String departmentId = dataObject.getString("departmentId");
     //手机号
     String mobile = dataObject.getString("mobile");
     //用户角色,1表示管理者,2表示使用者
     String isManager = dataObject.getString("isManager");
     //应用编号
     String project = dataObject.getString("project");

     //添加用户
     user.setId(id);
     user.setPhone(mobile);
     user.setTenantId("000000");
     user.setCode("");
     if(isManager.equals("1")){
      //管理员
      user.setRoleId("1529303109787967490");
     }else if(isManager.equals("2")){
      //一般用户
      user.setRoleId("1529302965017370625");
     }else{
      //会员(这个地方不会执行到,只要isManager不等于null)
      user.setRoleId("1355058724514836481");
     }
     user.setUserType(Integer.parseInt(isManager));
     user.setAccount(account);
     //密码是123456
     user.setPassword("10470c3b4b1fed12c3baac014be15fac67c6e815");
     user.setName(name);
     user.setRealName(name);

     user.setDeptId(departmentId);
     user.setStatus(1);
     //证明是那边过来的用户
     user.setRemark(type);
     switch (operate) {
      case "add":
       flag = userService.save(user);
       break;
      case "update":
       flag = userService.updateUser(user);
       break;
      case "delete":
       flag = userService.updateById(user);
       break;
      default:
       break;
     }
    } else if (type.equals("sso_department")) {
     Dept dept = new Dept();
     Long id = dataObject.getLong("id");
     //用户账号
     String title = dataObject.getString("title");
     //父级企业ID
     String parentId = dataObject.getString("parentId");
     //企业等级
     String level = dataObject.getString("level");
     //排序
     String sort = dataObject.getString("sort");
     //用户角色,1表示管理者,2表示使用者
     String isManager = dataObject.getString("isManager");
     //业务管路员ID
     String manager = dataObject.getString("manager");
     //业务管路员ID
     String project = dataObject.getString("project");
     dept.setId(id);
     dept.setDeptName(title);
     dept.setTenantId("000000");
     dept.setParentId(Long.parseLong(parentId));
     dept.setAncestors("0," + parentId);
     dept.setDeptCategory(3);
     dept.setFullName(title);
     dept.setSort(Integer.parseInt(sort));
     dept.setRemark(type);
     dept.setIsDeleted(0);
     switch (operate) {
      case "add":
       flag = deptService.save(dept);
       break;
      case "update":
       flag = deptService.updateById(dept);
       break;
      case "delete":
       flag = deptService.removeDept(id.toString());
       break;
      default:
       break;
     }
    }

   }
   return R.status(flag);
  }

  /**
   * 退出
   * @param ssoSessionKey
   * @return
   */
  @Override
  public String apiLogout(String ssoSessionKey) {
   JSONObject jsonObjectResult = new JSONObject();
   //请求接口地址
   String url = SsoLoginConstant.APILOGOUT_URL;
   Map<String, Object> paramMap = new HashMap<String, Object>();
   paramMap.put("ssoSessionKey", ssoSessionKey);
   try {
    String body = HttpUtil.createPost(url).form(paramMap).execute().body();
    if (StringUtils.isBlank(body)) {
     jsonObjectResult.put("code", 500);
     jsonObjectResult.put("msg", "请求失败");
     jsonObjectResult.put("data", "");
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
    JSONObject obj = JSONObject.parseObject(body);
    if (obj == null) {
     jsonObjectResult.put("code", 500);
     jsonObjectResult.put("msg", "请求失败");
     jsonObjectResult.put("data", "");
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
    String code = obj.get("code").toString();
    if ("200".equals(code)) {
     jsonObjectResult.put("code", 200);
     jsonObjectResult.put("msg", "请求成功");
     jsonObjectResult.put("data", obj.get("data"));
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }else{
     jsonObjectResult.put("code", 500);
     jsonObjectResult.put("msg", "请求失败");
     jsonObjectResult.put("data", "");
     jsonObjectResult.put("status", false);
     return jsonObjectResult.toJSONString();
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
   return jsonObjectResult.toJSONString();
  }


 }

先实现功能,在做优化~

  1. 控制器中的实现方法:
package org.springblade.modules.system.controller;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springblade.common.constant.TrainingSchemeConstant;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.entity.UserService;
import org.springblade.modules.system.service.ISsoLoginService;
import org.springblade.modules.system.service.impl.KnowledgeServiceImpl;
import org.springblade.modules.system.service.impl.SsoLoginServiceImpl;
import org.springblade.modules.system.service.impl.UserServiceImpl;
import org.springblade.modules.system.util.SsoLoginConstant;
import org.springblade.modules.system.util.TokenUtil;
import org.springblade.modules.system.vo.KnowledgeVO;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@RestController
@AllArgsConstructor
@RequestMapping("api/sso")
@Api(value = "", tags = "接口")
public class ApiSsoController {

 private final SsoLoginServiceImpl ssoLoginService;

 /**
  * 用户信息
  */
 private final UserServiceImpl userService;

 //private final RabbitTemplate rabbitTemplate;


 /**
  * 统一认证平台向第三方平台的接口发起请求。
  * 新增、修改、删除平台用户信息,将用户数据上传到我方
  *
  * @param
  */
 @PostMapping(value = "/pulluserinfo")
 public String pulluserinfo(@RequestBody String val) {
  JSONObject object = new JSONObject();
  R r = ssoLoginService.pullUserInfo(val);
  if (r.getCode() == 200) {
   object.put("msg", "操作成功");
   object.put("success", true);
   object.put("code", 200);
  } else {
   object.put("msg", "操作失败");
   object.put("success", false);
   object.put("code", 500);
  }
  return object.toJSONString();
 }

 /**
  * 登录鉴权
  * 
  */
 @GetMapping("/check_login")
 public R checkLogin(String ssoSessionKey) {
  //拿到接口返回值
  String result = ssoLoginService.checkLogin(ssoSessionKey);
  JSONObject jsonObject = JSON.parseObject(result);
  Integer code = jsonObject.getInteger("code");
  if (code == 200) {
   //操作成功
   JSONObject jsonObjectData = jsonObject.getJSONObject("data");
   //拿到用户名和密码
   if (jsonObjectData != null) {
    //将用户名传给前台,前台拿着去登陆去
    String account = jsonObjectData.getString("username");
    return R.data(account);
   } else {
    return R.fail("未找到该用户");
   }
  } else {
   //操作失败
   return R.fail("未找到该用户");
  }
 }


 /**
  * 查询平台用户信息
  * 
  */
 @GetMapping("/get_user")
 public String getUser(String projectKey) {

  return ssoLoginService.getUser(projectKey);
 }

 /**
  * 查询平台组织机构
  * 
  */
 @GetMapping("/get_department")
 public String getDepartment(String projectKey) {
  return ssoLoginService.getDepartment(projectKey);
 }

 /**
  * 退出时调用
  * 注销统一认证平台的用户信息
  */
 @GetMapping("/api_logout")
 public R apiLogout(String ssoSessionKey) {
  //拿到接口返回值
  String result = ssoLoginService.apiLogout(ssoSessionKey);
  JSONObject jsonObject = JSON.parseObject(result);
  Integer code = jsonObject.getInteger("code");
  if (code == 200) {
   return R.success("操作成功");
  } else {
   //操作失败
   return R.fail("接口请求出错");
  }
 }

}

整个后台的代码基本上就这些,基本上没啥难度,就是光操作的调用接口就可以了,主要麻烦点的是在前端,明天分享一下前端的实现。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。