# Oauth2接入

# 5.1 Code模式接入

# 5.1.1 请求code

请求头:header
Authorization: 值在页面登陆后,任意查看一个接口复制

http(s):{host}:{port}/api/auth/oauth/authorize?responseType=code&clientId=81699abe-c975-4a8d-bf6f-0a015568422e&redirectUri=http://192.168.97.163:8082/callback&scope=all
参数名 描述 类型 为空 备注
responseType 填写code String 必填
clientId 开发者使用api唯一标识 String 必填 认证系统分配
redirectUri 回调地址 String 必填
scope 默认all String
state 状态state String

如果没有登录,会自动跳转到统一认证登录页面,登录后,redirect_uri填写的回调地址会收到来自于统一认证的GET请求,并附带如下参数:

redirect_uri?code=<CODE>&state=<STATE>

例如:

http://192.168.97.163:8082/callback?code=0a015568422e&state=111
参数 说明
code 由认证服务器生成
state 第三方系统自己维护状态码

# 5.1.2 根据code获取access Token(HTTP POST)

接入的Web应用应在获取到code之后,向如下地址发送POST请求: https://{host}:{port}/api/auth/oauth/token

Json body:

{
   "clientId": "81699abe-c975-4a8d-bf6f-0a015568422e",
   "clientSecret": "d440049d-1b1a-49ba-8f56-0920bc83b9b2",
   "code": "F19353585910571175D17A0F9B2ACA28"
}
参数名 描述 类型 为空 备注
code 填写code String 必填 由第一步回调地址参数获得
clientId 开发者使用api唯一标识 String 必填 认证系统分配
clientSecret 与clientId对应的秘钥 String 必填 认证系统分配

返回结果:

{
   "code": 0,
   "data": {
      "accessToken": "f33fbb0be5c94d51b2ea3e23ad214175",
      "expiredIn": 3600,
      "scope": "all",
      "refreshToken": "0a775950fd9f463093bdcc2fa8e4cf76",
      "tokenType": "header"
   }
}

错误返回:

{
   "msg": "无效的code:e09715810ae641a6bb086d72a91b344!",
   "code": 10001
}
常见错误码 描述
10001 无效的code:%s!
10002 无效的client id:%s!
10003 回调链接(redirectUri)无效:%s!
10004 Client Secret:%s 校验失败!
10005 无效的Access Token: %s!

# 5.1.3 获取用户信息(HTTP GET)

接口地址:

http(s)://{host}:{port}/api/auth/profile

请求头:

参数名 描述 类型 为空
3rd-party-ac-token 第二步获取的token String 必填

返回值

参数名 描述
code 返回标识(0.正常 500.错误)
msg 操作信息
data.userId 用户id
data.sex 用户性别
data.avatar 头像地址
data.username 用户工号
data.nick 用户姓名
data.status 账号状态(0.启用 1.禁用)
data.phonenumber 手机号
data.email 邮箱
data.role.id 角色id
data.role.name 角色名称
data.role.code 角色代码(xs:学生,js:教师,子应用管理员:sub_application_manager,院系(单位)管理员:college_manage,游客:sys:visitor,开发商:sys:kfs)
data.role.deptId 部门id
data.role.deptCode 部门代码
data.role.deptName 部门名称

返回示例

{
  "code": 0,
  "msg": "请求成功",
  "data": {
    "userId": 47261,
    "sex": "男",
    "avatar": "",
    "username": "jc_data",
    "nick": "集成-数据中台",
    "status": "0",
    "phonenumber": "13888888888",
    "email": "xxxx@qq.com",
    "role": {
      "id": 1,
      "name": "学生",
      "code": "xs",
      "deptId": 1054,
      "deptCode": "0",
      "deptName": "半云学院"
    }
  }
}

错误示例:

{
   "msg": "无效的Access Token: 218204ed282249f6baead992a5297db!",
   "code": 10005
}

# 5.1.4 退出登陆 (HTTP GET)

调用地址:

http(s)://{ip}:{port}/api/auth/user/logout	

请求头:

3rd-party-ac-token: 由cas/oauth2接口获取用户access-token

返回值

参数名 描述
code 返回标识(0.正常)
msg 操作信息
data 返回信息

返回示例

{
   "code": 0,
   "msg": "请求成功",
   "data": null
}

# 5.1.5 Token校验 (HTTP POST)

调用地址:

http(s)://{ip}:{port}/api/auth/valid/token	

请求体(form data)

参数名 描述 类型 为空 备注
accessToken 登陆凭证 String 必填 由cas/oauth2接口获取用户access-token

返回值

参数名 描述
code 返回标识(0.正常)
msg 操作信息
data 返回信息

返回正确示例

{
   "code": 0,
   "msg": "请求成功",
   "data": null
}

返回错误示例

{
   "msg": "无效的Access Token: 0d0418da545746639c63da18df56d8f21!",
   "code": 10005
}

# 5.2 Java回调方法示例


@RestController
public class OAuth2Callback {

   private final AuthConfig authConfig;
   private final AuthClient authClient;

   public OAuth2Callback(AuthConfig authConfig, AuthClient authClient) {
      this.authConfig = authConfig;
      this.authClient = authClient;
   }

   /**
    * 处理oauth2 code
    *
    * @param code 由认证服务器转发 code
    * @return Resp<?>
    */
   @GetMapping("/oauth2/callback")
   public Resp<?> codeCallback(@RequestParam("code") String code) {

      AuthClientConfig oAuth2Config = authConfig.getOauth2();

      // step 1. 使用 code 换取用户access token
      Code2TokenReq req = new Code2TokenReq();
      req.setCode(code);
      req.setClientId(oAuth2Config.getClientId());
      req.setClientSecret(oAuth2Config.getClientSecret());
      Resp<AccessTokenInfo> accessTokenInfoResp = authClient.oauth2CodeToAccessToken(req);

      // step 2. 使用 access token 获取用户信息
      if (RespUtil.success(accessTokenInfoResp)) {
         AccessTokenInfo accessTokenInfo = accessTokenInfoResp.getData();
         String accessToken = accessTokenInfo.getAccessToken();
         CurrentRequest.setAccessToken(accessToken);

         // step 3. 跳转到自己的系统(请自行处理)
         return authClient.profile();
      }

      return accessTokenInfoResp;

   }

}

# 5.3 客户端密码模式

# 5.3.1 根据客户端密码获取access Token(HTTP POST)

http(s):{host}:{port}/api/auth/oauth/password/token
参数名 描述 类型 为空 备注
clientId 开发者使用api唯一标识 String 必填 认证系统分配
clientSecret 客户端访问密钥 String 必填
username 用户账号 String 必填
password 用户密码 String 必填

返回结果:

{
	"code": 0,
	"msg": "请求成功",
	"data": {
		"accessToken": "2c1abe81933f48b8929c83f7e3dd2f66",
		"expiredIn": 3600,
		"scope": "all",
		"refreshToken": "20a80eb27500499fbe830a6c34a59b5c",
		"tokenType": "header"
	}
}

错误返回:

{
	"code": 10000,
	"msg": "授权失败:账号或密码错误! 账号剩余4次尝试机会!",
}
常见错误码 描述
10000 授权失败:账号或密码错误! 账号剩余%s次尝试机会!
10002 无效的client id:%s!
10004 Client Secret:%s 校验失败!
10007 当前client id: %s,不支持 grant type: password

# 5.3.2 Token使用

根据5.1.3 获取用户信息5.1.4 退出登陆5.1.5 Token校验使用Token