# 身份验证

# 概述

身份验证为应用 web 系统提供了获取正在访问学加家的用户身份的能力,便于应用 web 系统构建登录流程。

# web端授权流程

  1. 用户点击三方应用入口(菜单或图标),前端容器使用iframe形式加载三方应用URL并携带SchoolID。
  2. 如果三方应用需要获取当前登录用户信息则需要发起用户授权(拼装授权URL并跳转至授权页面,默认静默授权)进入授权页面后检测当前用户登录状态(通过本地token获取当前用户预授权码)如果状态正常则返回三方redirect URL并携带当前用户预授权码(code)(如本地token失效则触发登录逻辑)。
  3. 三方应用通过预授权码与SchoolID等参数通过开放平台接口获取access_token和用户信息,并自行保持用户登录状态。

# 移动端授权流程

  1. 用户点击三方应用入口(菜单或图标),移动端容器使用web-view形式加载三方应用URL并携带SchoolID。
  2. 如果三方应用需要获取当前登录用户信息则需要发起用户授权(拼装授权URL并跳转至授权页面,默认静默授权)进入授权页面后检测当前用户登录状态(通过web-view jssdk 获取 token并获取当前用户预授权码)如果状态正常则返回三方redirect URL并携带当前用户预授权码(code)(如本地token失效则触发登录逻辑)。
  3. 三方应用通过预授权码与SchoolID等参数通过开放平台接口获取access_token和用户信息,并自行保持用户登录状态。

# 流程图

avatar

# 根据预授权码获取access_token

# 请求路径

https://auth.xuejj.com/oauth/token

# 请求方式

POST

# 请求header
字段名称 字段值 字段表述 是否必填
Authorization 值=Basic + 空格 + base64(appId:appSecret)
Content-Type application/x-www-form-urlencoded 固定值
User-Type op 固定值

Authorization的value由三部分组成:1.Basic, 2.空格,3.base64编码后的(appId:appSecret)

计算base64值的java代码如下:

byte[] toBytes = ("yourAppId" + ":" + "yourAppSecret").getBytes();
//appId使用base64的编码规则
String encoded = Base64.getEncoder().encodeToString(toBytes);
//这里就是Authorization的value,把三部分的字符串拼接起来
String headerValue = "Basic" + " " + encoded;
  • 注意:appId与appSecret只是生成Authorization,不需要写入header
字段名称 字段值 字段表述 是否必填
appId 为isv分配的appId
appSecret 为isv生成的appSecret
# 请求Body

body使用表单方式提交

表单字段为

字段名称 字段值 描述 是否必填
grant_type password 这里的值为固定值password
username 为预授权码code的值,注意code是一次性的,并且只有5到20分钟有效期。如果获取access_token失败,需要引导用户重新授权。
# 返回示例
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiIxMzQ4NDYyMDMxMiIsImljb24iOiIiLCJhdXRob3JpdGllcyI6WyJ1c2VyIl0sImNsaWVudF9pZCI6InVjbSIsInJvbGVfbmFtZSI6InVzZXIiLCJ1c2VyX2lkIjoyNzUyMDIsInJvbGVfaWQiOiIxMTIzNTk4ODE2NzM4Njc1MjAyIiwiZXh0ZXJuYWxfdXNlcl9ubyI6IjI3NTIwMiIsInBob25lIjoiMTM0ODQ2MjAzMTIiLCJzY29wZSI6WyJhbGwiXSwic2Nob29sSWQiOjYxMDExMywibmFtZSI6IuWtmeeQpiIsImV4cCI6MTU5OTYyMjM5Mywic3lzdGVtX3NvdXJjZSI6Im9wIiwianRpIjoiYTJhNTQwMWItNWQwNC00MzgzLTljNTItZjk3YzExYzExMTVjIn0.p5eaPoz_zXTclPBNLyP-srIoWPPC7QroSsPMQDJITaTGsmP6CTJ_gNImew1AFiUVafmiZ12Z68JFixLxdBpFPfXkbXMrVKs2g-ZhqL4ITCsBTo7o4YiLAZ4wTSYe_sYPKEP_LggPOA8Bww60WjO-xipkzsrwdhpV_3aj1iJ6Eux-KKsR3SQ1tzHBSysvoE3NBxcQQ-lENOlWQUy1rHvwf4qiCEs-CAmeT7nnLKRjZtaQoTfb3pq-CgXKTSgbJGl66cfqyU74o0lziZ2fsLCzkUdbDo8pnRItd3ciJ88F5i3kZstDaD9SRMczA9Jmm52SC6ZpYQnOY5_7UJ3o6ik9-Q",
  "token_type": "bearer",
  "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiIxMzQ4NDYyMDMxMiIsImljb24iOiIiLCJhdXRob3JpdGllcyI6WyJ1c2VyIl0sImNsaWVudF9pZCI6InVjbSIsInJvbGVfbmFtZSI6InVzZXIiLCJ1c2VyX2lkIjoyNzUyMDIsInJvbGVfaWQiOiIxMTIzNTk4ODE2NzM4Njc1MjAyIiwiZXh0ZXJuYWxfdXNlcl9ubyI6IjI3NTIwMiIsInBob25lIjoiMTM0ODQ2MjAzMTIiLCJzY29wZSI6WyJhbGwiXSwic2Nob29sSWQiOjYxMDExMywiYXRpIjoiYTJhNTQwMWItNWQwNC00MzgzLTljNTItZjk3YzExYzExMTVjIiwibmFtZSI6IuWtmeeQpiIsImV4cCI6MTYwMDEzODc5Mywic3lzdGVtX3NvdXJjZSI6Im9wIiwianRpIjoiYTU2M2EzNmQtMzU0NC00NDFjLWE2ZjgtODhlZjExOWY3ZWQzIn0.TP37P6OuxAG0UVsSB4vqHfmlz4eWLYg7z-TxM3DL8wBhp-jXCyK99Y0XpW-8wvg47h2EQ0y5bhq6w8Qvuj8OoYU5s0VTakCnOKwQQ_CY0enT2GqQmXvd-A26Lqzm1ReTaTe1ebh_HAeWEs7m0dkveoU69yawjjk1wgLciEa3hHYYR8hFdrZKW9vPHsVNQJkpNqUNmbDDIURXHevBMzZCKex9IwbDsfNDcXVZ7yWAx8XhTpX7030VASVR_Q8_HD_wnTllKq8M0CcmdTF_kxeTDeenc7E89G1GcCxoQBh_JF8THFRbG9-M16ObC7qbxoDs-zv-AY9hUdvIjmlhdVWSVA",
  "expires_in": 3600,
  "role_name": "openapi",
  "user_id": 275xxx,
  "role_id": "1123598816738675202",
  "external_user_no": "275202",
  "phone": "134846xxx",
  "schoolId": xxx,
  "name": "xxx",
  "icon": "",
  "system_source": "op",
  "app_id": "your_app_id",
  "jti": "a2a5401b-5d04-4383-9c52-f97c11c1115c"
}

# 获取用户信息

access_token是标准jwt格式,可以通过解析access_token来获取用户的基本信息。为确保用户信息的可靠,必须使用以下公钥来解析jwt

# 公钥
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuGmHv9bVGTLa3a3K6z0XxzttmNxwzAr6ECnbEpwysLCPgNNSgyIgquv2mo0+KkZJlajhAj4gX/qoJM5HaI98kB8gt05JO0alk1oVLHNg8rDEvFp/gedzRayJiLr+C+LT9k4Su9C0RlGlJ7jh6pJbIa5OTQFA+7mEqfipVXyP5x+SjjNN4nETfh+5t7vuxhzIefxgLUjWaWMc/pSFDTEvIvI0B0I6yAXwS1/K5hWpDx9qP6bH/AuTAG8eqG+uHP145WPy98uTPd0BF5JLqtl5j+a+15nlIMWvK5sTe9x+NyD03lfxUmurXtU7FXUSSrHpBNAumrMD1gaqJBomUqwl2wIDAQAB
-----END PUBLIC KEY-----
# 解析jwt的java示例代码如下:

/**
* 注意,这里使用使用了jjwt库来解析jwt,
* 更多使用请参考https://github.com/jwtk/jjwt
*
*/
public static Claims parseJWTUsingPubKey(String accessToken) {
		String PUB_KEY_STR = loadPubKey();
		Objects.requireNonNull(jsonWebToken, "accessToken is null");
		try {
			java.security.spec.X509EncodedKeySpec bobPubKeySpec = new java.security.spec.X509EncodedKeySpec(
				new BASE64Decoder().decodeBuffer(PUB_KEY_STR));
			java.security.KeyFactory keyFactory;
			keyFactory = java.security.KeyFactory.getInstance("RSA");
			PublicKey publicKey = keyFactory.generatePublic(bobPubKeySpec);
			return Jwts.parser()
				.setSigningKey(publicKey)
				.parseClaimsJws(jsonWebToken).getBody();
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
			return null;
		}
	}
# Claims里面包含的字段为
字段名称 说明 描述 备注
userId 用户id 学加家中用户的唯一凭证,不为空
name 用户称呼 用户称呼,可能为空
icon 用户头像 有可能为空
Last Updated: 9/27/2020, 11:49:41 AM