Web服务统一身份认证协议设计与实现
创始人
2024-05-12 00:47:23
0

单点登录(SSO)是目前比较流行的企业业务整合的解决方案之一,它的机制是在企业网络用户访问企业网站时作一次身份认证,随后就可以对所有被授权的网络资源进行无缝的访问,而不需要多次输入自己的认证信息.Web服务具有松散耦合、语言中立、平台无关性、开放性的特性,通过对集中单点登录模型的分析和比较,提出了基于Web服务和token-id的单点登录管理框架.介绍了该系统的体系机构及关键部分的工作原理.

本项目主要是采用spring boot +mysql 实现。重点描述如何重代码结构上实现 Web服务统一身份认证协议设计与实现功能。

主要功能如下

  1. token生成与管理
  2. 系统接入token 实现sso 单点登录
  3. 统一身份token 认证与校验
  4. 分布式系统接入sso模式

项目整体结构

在这里插入图片描述

一:sso 管理

原理,利用http 头部信息保存token 匹配服务器的session信息,进行校验。当用户首次登录系统,注册sso 信息

(1):注册sso token

    public ResultPo register(String sessionId, String token, long uid) {String session = getSession(uid, token);if (session != null && session.equals(sessionId)) {ResultPo result = ResultPo.create(200, "sso token exist");SSoPo po = redisService.getPo(SSoPo.class, new MongoPrimaryKey("session_id", session));if (po != null) {po.setMtime(TimeUtils.Now());redisService.updatePo(po);result.appendData("sso", po);return result;}} else if (session != null) {this.removeSession(session, token);}SSoPo sso = new SSoPo();sso.setUid(uid);sso.setSessionId(sessionId);sso.setToken(token);sso.setMtime(TimeUtils.Now());SSoPo po = redisService.getPo(SSoPo.class, sso.getPrimaryKeys());if (po != null) {po.setMtime(TimeUtils.Now());redisService.updatePo(po);ResultPo result = ResultPo.create(200, "sso token exist");result.appendData("sso", sso);return result;}redisService.savePo(sso);ResultPo result = ResultPo.create(200, "sso register successful");result.appendData("sso", sso);redisService.hsetString(getSessionPool(token), uid + "", sessionId, sso.getClass().getAnnotation(Cache.class).timestamp());return result;}/*** token 生成器** @return*/public String generateTokeCode() {String value = System.currentTimeMillis() + new Random().nextInt() + "";System.out.println(value);long currentTime = System.currentTimeMillis();SimpleDateFormat formatter = new SimpleDateFormat("yyyy年-MM月dd日-HH时mm分ss秒");Date date = new Date(currentTime);System.out.println(formatter.format(date));//获取数据指纹,指纹是唯一的try {MessageDigest md = MessageDigest.getInstance("md5");byte[] b = md.digest(value.getBytes());//产生数据的指纹//Base64编码BASE64Encoder be = new BASE64Encoder();be.encode(b);System.out.println(be.encode(b));return be.encode(b);//制定一个编码} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return null;}

把信息保存到中心服务中,把用户uid sessionid token 三者关系建立起来。

(2):校验sso

 public ResultPo validateSession(String sessionId, String token) {SSoPo sso = redisService.getPo(SSoPo.class, new MongoPrimaryKey("session_id", sessionId));if (sso == null) {return ResultPo.create(ErrorCode.SESSION_ERROR, "session not found");}//过期boolean expr = TimeUtils.Now() > (sso.getMtime() + sso.getClass().getAnnotation(Cache.class).timestamp());if (expr) {removeSession(sso.getSessionId(), token);return ResultPo.create(ErrorCode.SESSION_ERROR, "session long old");}ResultPo po = ResultPo.create(200, "session validate successful");po.appendData("sso", sso);return po;}

用户在分布式系统中请求都携带此token 中,不用在此进行登录或者用户信息的校验,只需要通过token 和application所颁发的token 进行校验。

/*** 验证web 应用是否合法** @param serverId* @param token* @return*/public ResultPo validateApp(long serverId, String token) {HashMap params = new HashMap<>();params.put("serverId", serverId);params.put("token", token);String json = HttpUtil.getInstance(token).post("", this.url + "/sso/appValidate", params);return BaseUtils.getResultPo(json);}

(3):token 销毁

 @Overridepublic ResultPo removeSession(String sessionId, String token) {SSoPo sso = redisService.getPo(SSoPo.class, new MongoPrimaryKey("session_id", sessionId));if (sso == null) {return ResultPo.create(200, "");}redisService.deletePo(SSoPo.class, new MongoPrimaryKey("session_id", sessionId));redisService.deleteHField(getSessionPool(token), sso.getUid() + "");return ResultPo.create(200, "successful");}

二:服务器节点接入

服务节点的介入,任何系统授信信息都需要通过中心服务器颁发的token 与appid 进行注册校验,提供application的注册信息。颁发给每个系统。

(1):系统节点接入

应用节点定义:

@Document(collection = "server_node")
@Cache(cache = true)
public class ServerNode implements IMongoPo {@Field("server_id")@PrimaryKey(name = "server_id")@Indexed(name = "server_id", unique = true)  //索引  name为索引名称,unique=true,唯一索引private int serverId;@Field("type")private String type;@Field("name")private String name;@Field("url")private String url;@Field("token")private String token;@Field("port")private int port;@Field("weight")private int weight;@Field("status")private int status;

应用接入:

 @Overridepublic ResultPo register(ServerNode serverNode) {boolean successful = serverDao.add(serverNode);if (successful) {return ResultPo.create();}return ResultPo.create(500, "create app error");}

分系统接入
定义一个服务的主要信息

"sso": [{"id": 1,"url": "http://127.0.0.1","port": 8524,"weight": 1,"token": "123456"}],

应用校验

应用系统进行网络通讯的时候,首先会进行application校验。

  @RequestMapping("appValidate")public ResultPo appValidate(HttpServletRequest request, long serverId, String token) {ResultPo resultpo = serverService.get(serverId);Object obj = resultpo.get("data");if (obj == null) {resultpo.setCode(500);resultpo.setMessage("application validate error!");return resultpo;}ServerNode node = (ServerNode) obj;if (!node.getToken().equals(token)) {resultpo.setCode(500);resultpo.setMessage("application validate error! token not march");return resultpo;}resultpo.setCode(200);resultpo.setMessage("application validate successful");return resultpo;}
package com.graduation.online.proxy;import com.graduation.online.base.BaseUtils;
import com.graduation.online.base.enums.ServerType;
import com.graduation.online.base.model.ResultPo;
import com.graduation.online.base.service.ServerNodeService;
import com.graduation.online.base.utils.HttpUtil;import java.util.HashMap;public class SSoAgentServer extends BaseAgent {public SSoAgentServer() {super(ServerNodeService.getInstance().getServerNode(ServerType.SSO));}public ResultPo register(String sessionId, long uid) {HashMap params = new HashMap<>();params.put("sessionId", sessionId);params.put("token", token);params.put("uid", uid);String json = HttpUtil.getInstance(token).post(sessionId, this.url + "/sso/register", params);return BaseUtils.getResultPo(json);}/*** 验证系统用户session 同一身份** @param sessionId* @return*/public ResultPo validateSession(String sessionId) {HashMap params = new HashMap<>();params.put("sessionId", sessionId);params.put("token", token);String json = HttpUtil.getInstance(token).post(sessionId, this.url + "/sso/validate", params);return BaseUtils.getResultPo(json);}/*** 验证web 应用是否合法** @param serverId* @param token* @return*/public ResultPo validateApp(long serverId, String token) {HashMap params = new HashMap<>();params.put("serverId", serverId);params.put("token", token);String json = HttpUtil.getInstance(token).post("", this.url + "/sso/appValidate", params);return BaseUtils.getResultPo(json);}public long getSSoUId(String sessionId) {HashMap params = new HashMap<>();params.put("sessionId", sessionId);params.put("token", token);String json = HttpUtil.getInstance(token).post(sessionId, this.url + "/sso/uid", params);ResultPo result = BaseUtils.getResultPo(json);if (result.get("uid") == null) {return -1;}return Long.parseLong(result.get("uid").toString());}public String getSession(long uid) {HashMap params = new HashMap<>();params.put("uid", uid);params.put("token", token);String json = HttpUtil.getInstance(token).post(null, this.url + "/sso/getSession", params);ResultPo result = BaseUtils.getResultPo(json);if (result.get("sessionId") == null) {return "";}return result.get("sessionId").toString();}public ResultPo removeSession(String sessionId) {HashMap params = new HashMap<>();params.put("sessionId", sessionId);params.put("token", token);String json = HttpUtil.getInstance(token).post(sessionId, this.url + "/sso/remove", params);return BaseUtils.getResultPo(json);}
}

分系统用户进行登录时候,只需要在登录授权一次,既可以在任何系统进行数据读取,

三:简单演示

在这里插入图片描述

当用户登录系统后
在这里插入图片描述

后台sso 系统接收到用户认证信息

用户授权后,进入到系统

系统为应用授权
在这里插入图片描述

总结:本系统采用web 的sso 统一身份认知,利用一个简单的,实现web 认证管理,加密认证,分布式系统应用授权认证。

代码地址:git@github.com:twjitm/graduation-online-server-code.git

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...