单点登录 #

单点登录和开发语言,框架无关,这里以前端vue,后端springboot(java)进行说明,后面不再赘述。

JWT #

1. payload 具有如下信息: #

  • iss: cmcim
  • exp: 过期时间 Date类型
  • clientType: 客户端类型 1 网页,2 PC客户端,3 移动端
  • userId: 用户唯一标识,同集成系统的用户ID
  • clientIp: 客户端IP地址
  • deviceId: 客户端设备唯一标识

2. 加密算法采用HS256,密钥为UPush的AppSecret参照 (opens new window) #

3. Yo信生成jwt代码举例 #

  JWT.create()
          .setExpiresAt(date) // 默认为颁发时间5分钟后过期
          .setIssuedAt(new Date()) // token颁发时间
          .setIssuer("cmcim") // 颁发者固定为cmcim
          .setPayload("clientType", 2)
          .setPayload("userId", "7e3aea655b5489eac146434db452d290")
          .setPayload("clientIp", "47.342.101.23")
          .setPayload("deviceId", "6cdc0810a1b96e27")
          .setSigner("HS256", upushSecret.getBytes(StandardCharsets.UTF_8)) // upushSecret为密钥
          .sign();

4. 集成系统解析JWT举例 #

  • 方式一,如果项目中已经使用了hutool,建议直接使用hutool中的JWT解析。如果没有可以在pom添加如下依赖:
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.8.11</version>
</dependency>

hutool解析:

JWT jwt = JWT.of(jwtToken);
// 密钥为UPush的AppSecret
boolean b = jwt.setKey(upushSecret.getBytes(StandardCharsets.UTF_8)).verify();
if (!b) {
    log.error("jwt token invalid");
    return;
}

// 取得userId,取得其他payload中的键值同理
String userId = (String) jwt.getPayloads().get("userId");

  • 方式二,由于有的系统中并没有集成hutool,hutool是一个工具集其中有很多功能,没有必要为了解析jwt冗余引用依赖,可以引用专门解析jwt的库,如下:
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.4.0</version>
</dependency>

java-jwt解析:

// 密钥为UPush的AppSecret
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(upushSecret)).withIssuer("cmcim").build();
DecodedJWT decodedJWT;
try {
  decodedJWT = jwtVerifier.verify(token);
} catch (TokenExpiredException e){
  // ...
} catch (JWTVerificationException e) {
  // ...
}

// 取得userId,取得其他payload中的键值同理
String userId = decodedJWT.getClaim("userId").asString()

鉴权 #

从Yo信跳转到集成系统页面如何鉴权?

  • 前端
    vue的项目中都会对路由的全局拦截用于判断登录状态做页面跳转,配置白名单无需鉴权即可访问的路径等等。Yo信在做跳转时会在Url携带参数yx_access_token。
router.beforeEach((to, from, next) => {
  // yx_access_token不为空表示是从Yo信跳转过来的链接
  if (to.query?.yx_access_token) {
    
  }
})

前端拿到yx_access_token,有如下两种鉴权方式:

  1. 使用yx_access_token向后端做登录请求,这种方式对前/后端代码的侵入性最小推荐使用。发送登录请求前注意判断是否已经是登录状态,因为可能会多次且频繁的从Yo信跳转到集成系统画面,没必要每次跳转都执行登录请求。

  2. 前端直接使用yx_access_token对服务端请求,即前端直接把yx_access_toke当成系统本身的token去使用,由服务端判断是Yo信的token,还是系统本身的token,再进行鉴权。


  • 后端
  1. 对应前端的方式1,后端添加一个使用yx_access_token登录的接口,由前端调用,返回和正常登录一样的内容即可。

  2. 对应前端的方式2,后端需要在校验系统token的位置添加对yx_access_token的校验,并构建和普通请求一样的请求上下文。无论是鉴权框架是Spring Securety,Shiro,或者自定义的拦截器都适用。