平台 OAuth2.0 认证服务

OAuth 2.0 是目前最流行的授权机制,用来授权第三方应用,获取用户数据。OAuth2.0 标准授权步骤,Server 端向 Client 端下放 Code 码,Client 端再用 Code 码换取授权 Token。如下图:

授权码模式

平台“企业集成”应用提供了 OAuth 2.0 认证服务,支持平台应用或第三方应用作为客户端,访问认证服务。

同时,平台提供了客户端模板文件 sso-client.zip,用于访问认证服务。放在平台应用中只需简单配置即可使用。

认证服务

平台通过企业集成的模块 oauth2 提供认证服务,原理实现参考 Sa-Token

image-20240709110250876

表结构信息

客户端信息表

客户端信息表用来配置需要进行 OAuth2.0 认证的第三方应用。其中允许的授权地址、具体授权信息字段可配置多个,多个情况使用英文逗号分隔。

客户端配置信息

配置数据如下:

客户端配置信息

会话数据表

会话数据表主要用来记录 OAuth2.0 认证过程的缓存数据。

会话数据

配置客户端

企业集成应用提供“认证客户端”,用来添加客户端。客户端 ID 和客户端密钥在访问认证服务中使用

图 0

API 接口

接口名称 接口地址 请求方法
well-known oauth2/.well-known/openid-configuration GET
认证 oauth2/api/authorize GET
登录 oauth2/api/doLogin POST
授权 oauth2/api/doConfirm POST
token 获取 oauth2/api/token POST
token 刷新 oauth2/api/refresh POST
token 回收 oauth2/api/revoke POST
用户信息 oauth2/userinfo POST
登出 oauth2/logout GET

认证

URL:
    https://门户域名/integration/oauth2/api/authorize?response_type=code&client_id=xxx&scope=userinfo&redirect_uri=xxx
参数:
    门户域名:使用租户中企业门户的域名
    response_type:固定参数 code,表示授权码模式
    client_id:在认证客户端中设置的客户端 iD
    scope:在认证客户端中设置的具体授权信息
    redirect_url:登录成功后的重定向地址,下发授权码 code

使用客户端模板 sso-client.zip 时,重定向地址写为 https://门户域名/应用名/main/oauth/callback%3Flocation=/

  • 重定向地址为:/main/oauth/callback
  • %3F 为转义的 ?
  • location 表示认证成功后打开的地址

获取 token

URL:
    https://门户域名/integration/oauth2/api/token?grant_type=authorization_code&client_id=xxx&client_secret=xxx&code=xxx
参数:
    门户域名:使用租户中企业门户的域名
    grant_type: 固定参数 authorization_code,表示授权码模式
    client_id:在认证客户端中设置的客户端 iD
    client_secret:在认证客户端中设置的客户端密钥
    code:下发的授权码
返回:
    access_token

获取用户信息

URL:
    https://门户域名/integration/oauth2/userinfo?access_token=xxx
参数:
    门户域名:使用租户中企业门户的域名
    access_token: 调用获取 token API 的返回值

认证过程

浏览器访问认证服务 https://门户域名/integration/oauth2/api/authorize?response_type=code&client_id=xxx&scope=userinfo&redirect_uri=xxx

显示认证服务登录页面,如下图所示,支持通过环境变量配置为其它页面

图 1

用户首次登录后,跳转到授权页面,如下图所示,支持通过环境变量配置为其它页面

授权

登录成功后,跳转到重定向地址

客户端

使用平台认证服务进行登录验证的系统,称为客户端。可以是平台本身,也可以是第三方。

平台应用作为客户端

平台提供客户端模板文件 sso-client.zip 用于放到平台的应用中,只需配置几个内容,即可访问认证服务

  • UI2/pcx/oauth2.user.serviceMetaInfo.json 文件用于设置认证回调接口为匿名访问
  • service/main 目录下的文件提供认证回退接口

认证回调接口

认证服务重定向地址访问的是客户端模板文件中的 /main/oauth/callback 服务,代码如下,接收两个参数

  • code: 认证服务下发的授权码
  • location:重定向地址中携带的参数
    @RequestMapping(value = "/main/oauth/callback", method = RequestMethod.GET)
    public void oauthcallback(@RequestParam(name = "code") String code,@RequestParam(name = "location") String location) throws Exception {
        oauthProcessor.process(code, location);
    }

oauthcallback 方法的主执行链路,代码如下

  • 通过 code 调用认证服务 API 获取 accessToken
  • 通过 accessToken 调用认证服务 API 获取 userInfo
  • 注册用户
  • 用户登录
  • 跳转到 location 参数指定的页面
    public void process(String code,String location) {
        if(StringUtils.isBlank(code)) {
            throw new IllegalArgumentException("oauth回调code不能为空!");
        }

        if(StringUtils.isBlank(location)) {
            throw new IllegalArgumentException("oauth登录的location不能为空!");
        }
        String accessToken = this.onRetriveAccessToken(code);
        U oauthUserInfo = this.onRetriveOauthUserInfo(accessToken);
        String session = null;
        if(this.checkNeedLogin(oauthUserInfo)) {
            String[] shadowUserLoginInfo = this.onRegisteUser(oauthUserInfo, oauthConfig);
            session = this.onLogin(shadowUserLoginInfo);
        }
        this.onProcessReponse(session, location);
        this.onOauthSuccess(oauthUserInfo,session);
    }

配置认证参数

在 java/main/config/OauthConfig.java 文件中配置认证参数

  • clientId:在认证客户端中设置的客户端 iD
  • clientSecret:在认证客户端中设置的客户端密钥
  • oauthServer:认证服务地址,使用租户中企业门户的域名/integration
  • redirectUri:认证回调地址,使用租户中企业门户的域名/应用名/main/oauth/callback,已在 oauth2.user.serviceMetaInfo.json 文件中设置为匿名访问

示例代码如下

    public String clientId = "1001";
    public String clientSecret = "aaaa-bbbb-cccc-dddd-eeee";
    public String oauthServer = "https://entryhlzs4-vip.h.xcaas.net/integration";
    public String redirectUri = "https://entryhlzs4-vip.h.xcaas.net/oauth2/main/oauth/callback";

第三方应用作为客户端

使用认证服务认证并登录,过程如下

  • 访问认证服务,传入回调地址 redirect_uri
  • 认证服务器验证通过后,重定向到 redirect_uri,同时携带授权码 code
  • 使用 code 调用认证服务的接口,获取授权 token
  • 使用授权 token,调用认证服务的接口,获取用户信息
  • 系统根据用户信息,在系统中自动注册用户,完成登录,并重定向到要真正打开的地址

第三方应用可以参考平台提供的客户端模板文件中的 Java 部分,提供认证回调接口,在接口中获取用户信息,并实现登录跳转

自定义登录及授权页面

认证服务的登录和授权页面,可以通过企业集成的“环境变量”自定义。

添加登录和授权页面

页面中,登录和授权的 JS 代码,可以参考下面的代码

  • 登录 JS 代码
//登录
onLoginBtnClick = async(event) => {
    const pageData=this.comp("pageData").getCurrentRow();
    let {response_type,client_id,redirect_uri,scope}=this.params;
    //认证服务地址
    const oauth2ServerUrl="https://entryhlzs4-vip.h.xcaas.net/integration";
    // 认证服务登录地址
    const loginUrl = '/oauth2/api/doLogin';
    try {
        const header={
            "accept": "application/json",
            // 要使用这个类型请求
            "content-type": "application/x-www-form-urlencoded"
        }
        const {data,statusCode}=await this.request({url:`${oauth2ServerUrl}/${loginUrl}?client_id=${client_id}`,header,method:"post",data:{name:pageData.username,pwd:pageData.password}});
        if(statusCode === 200 && data.code === 200){
            // 登录成功后继续认证
            window.location.href = oauth2ServerUrl+'/oauth2/api/authorize?response_type=' + response_type + "&client_id=" + client_id + "&redirect_uri=" + redirect_uri + "&scope=" + scope 
        }else{
            message.error("登录失败!"+data.message);
        }
    } catch (error) {
        message.error("登录失败!");
        throw error;
    }

}
  • 授权 JS 代码
//授权
onAuthBtnClick = async(event) => {
    //获取参数
    let {response_type,client_id,redirect_uri,scope}=this.params;
    //认证服务地址
    const oauth2ServerUrl="https://entryhlzs4-vip.h.xcaas.net/integration";
    //认证服务授权地址
    const authUrl="/oauth2/api/doConfirm";
    try {
        const header={
            "accept": "application/json",
            // 要使用这个类型请求
            "content-type": "application/x-www-form-urlencoded"
        }
        const {data,statusCode}=await this.request({url:`${oauth2ServerUrl}/${authUrl}`,header,method:"post",data:{client_id, scope}});
        if(statusCode === 200 && data.code === 200){
            // 登录成功后继续认证
            window.location.href = oauth2ServerUrl+'/oauth2/api/authorize?response_type=' + response_type + "&client_id=" + client_id + "&redirect_uri=" + redirect_uri + "&scope=" + scope 
        }else{
            message.error("登录失败!"+data.message);
        }
    } catch (error) {
        message.error("登录失败!");
        throw error;
    }
}

设置页面匿名访问

通过 IDE 角色权限设置,设置“登录”及“授权”页面匿名访问

图 19图 20图 21

设置环境变量

将页面的访问地址,配置到企业集成-环境配置的登录视图、授权视图中

平台访问认证服务

认证服务

使用租户管理员登录后,在“应用服务管理”下新增“企业集成”应用,并到企业门户下进行服务注册

图 8

图 9

企业集成服务注册完成后,在门户“企业集成 -> OAuth2 -> 认证客户端”下新增客户端信息

图 10

客户端

在租户下“我的开发 -> 企业应用”下新增“SpringBootReact 空白模板”应用,作为访问认证服务的客户端。

  • 使用本地 IDE,将 sso-client.zip 文件复制到应用中
  • 使用云 IDE,参考《应用导入导出》中的通过 IDE 导入源码包,使用追加模式,导入 sso-client.zip

图 11

图 2

在 java/main/config/OauthConfig.java 文件中,修改认证配置参数:oauthServer、clientId、clientSecret、redirectUri

图 14

完成以上操作后,通过认证服务的认证接口“企业门户域名/integration/oauth2/api/authorize”进行访问即可,例如 https://entryhlzs4-vip.h.xcaas.net/integration/oauth2/api/authorize?response_type=code&client_id=1001&scope=userinfo&redirect_uri=https://entryhlzs4-vip.h.xcaas.net/main/oauth/callback%3Flocation=/

图 1

results matching ""

    No results matching ""