核心内容摘要
心跳预警!解码韩国美女热舞背后的极致诱惑与审美风暴
Oauth2Request你现在展示的Oauth2Request类,是 Jeecg 项目基于 JustAuth 框架实现的自定义SINOSOFT平台 OAuth 登录请求处理类,继承自 JustAuth 的AuthDefaultRequest,重写了 OAuth 登录流程的核心方法,完成「获取授权码 → 换取访问令牌 → 获取用户信息」的完整逻辑。
我们先
总结整体功能,再逐方法拆解核心逻辑和关键细节。
整体功能
总结这个类的核心作用是实现SINOSOFT平台专属的 OAuth 登录请求处理流程,覆盖了 JustAuth 框架的默认逻辑,适配该平台的接口规范(请求方式、参数格式、响应格式),最终返回封装好的用户信息和令牌,供后端完成登录会话创建。
整体流程对应:前端触发登录 → 生成授权地址(authorize())→ 用户授权后回调 → 用授权码换令牌(getAccessToken())→ 用令牌换用户信息(getUserInfo())→ 封装结果返回(login())
逐部分/逐方法详细解读
类属性与构造方法(初始化核心配置)// 定义HTTP请求超时时间:20秒privatefinalinttimeout=20000;// 构造方法1:传入AuthConfig(对应yml中的SINOSOFT配置),指定自定义平台为SinosoftSource.SINOSOFTpublicOauth2Request(AuthConfigconfig){super(config,SinosoftSource.SINOSOFT);}// 构造方法2:额外传入状态缓存,用于存储OAuth的state参数(防CSRF)publicOauth2Request(AuthConfigconfig,AuthStateCacheauthStateCache){super(config,SinosoftSource.SINOSOFT,authStateCache);}关键解读:构造方法调用父类AuthDefaultRequest的构造方法,完成「配置注入」和「平台绑定」,让框架知道当前处理的是SINOSOFT平台。
timeout定义了 HTTP 请求的超时时间(20秒),防止请求第三方接口时无限阻塞(不过当前代码中未直接使用该属性,可优化补充到 HttpRequest 中)。
AuthConfig封装了 yml 中的client-id、redirect-uri等配置参数,后续方法可通过super.config或this.config获取。
核心入口方法:login(AuthCallback authCallback)这是 OAuth 登录的入口方法,接收前端回调传递的授权码(authCallback封装了code、state等参数),整合整个登录流程,返回最终结果。
@OverridepublicAuthResponseObjectlogin(AuthCallbackauthCallback){try{//
校验授权码(code)是否存在,不存在则抛出AuthExceptionAuthChecker.checkCode(this.source,authCallback);//
用授权码换取访问令牌(access_token)AuthTokenauthToken=this.getAccessToken(authCallback);//
用访问令牌换取用户信息(AuthUser)AuthUseruser=this.getUserInfo(authToken);//
封装成功结果,返回用户信息returnAuthResponse.builder().code(AuthResponseStatus.SUCCESS.getCode()).data(user).build();}catch(Exceptione){//
异常处理:封装错误码和错误信息,返回失败结果Log.error("Failed to login with oauth authorization.",e);interrorCode=AuthResponseStatus.FAILURE.getCode();StringerrorMsg=e.getMessage();if(einstanceofAuthException){AuthExceptionauthException=(AuthException)e;errorCode=authException.getErrorCode();if(StringUtils.isNotEmpty(authException.getErrorMsg())){errorMsg=authException.getErrorMsg();}}returnAuthResponse.builder().code(errorCode).msg(errorMsg).build();}}关键解读:AuthChecker.checkCode():JustAuth 提供的工具方法,校验authCallback.getCode()是否为空,为空则抛出「授权码不存在」的异常,避免后续流程空指针。
流程串联:将「获取令牌」和「获取用户信息」两个核心步骤串联,最终返回AuthResponse(框架统一的响应封装类)。
异常兜底:捕获所有异常,区分AuthException(框架自定义异常)和普通异常,封装对应的错误信息,保证接口不会直接抛出异常崩溃,提高健壮性。
令牌获取方法:getAccessToken(AuthCallback authCallback)重写父类方法,实现用授权码(code)换取SINOSOFT平台的访问令牌,适配该平台的响应格式。
@OverrideprotectedAuthTokengetAccessToken(AuthCallbackauthCallback){//
构建获取令牌的接口地址(调用自身重写的accessTokenUrl()方法)StringaccessTokenUrl=super.accessTokenUrl(authCallback.getCode());//
创建GET请求,访问令牌接口HttpRequestrequest=HttpUtil.createRequest(Method.GET,accessTokenUrl);//
执行请求,获取响应体HttpResponseexecute=request.execute();Stringbody=execute.body();//
解析响应体(JSON格式),提取令牌(该平台令牌存在于"result"字段中)JSONObjectjsonObject=JSONObject.parseObject(body);StringaccessToken=jsonObject.getString("result");//
封装为AuthToken对象返回(JustAuth框架统一的令牌封装类)AuthTokenauthToken=AuthToken.builder().accessToken(accessToken).build();returnauthToken;}关键解读:依赖accessTokenUrl()构建接口地址,后续会解读该方法。
使用Hutool的HttpUtil发送 HTTP 请求(简化 HTTP 操作,无需手动封装 HttpClient),请求方式为GET(适配SINOSOFT平台的令牌接口要求)。
响应解析:该平台的令牌接口返回结果中,令牌直接存储在result字段中(如{"result": "xxx-token-xxx"}),与 JustAuth 原生平台的响应格式不同,因此需要自定义解析逻辑。
仅封装了accessToken:如果平台返回「刷新令牌」「令牌过期时间」等信息,可补充到AuthToken中(如authToken.setRefreshToken(refreshToken))。
令牌接口地址构建:accessTokenUrl(String code)重写父类方法,构建SINOSOFT平台获取令牌的接口地址。
@OverrideprotectedStringaccessTokenUrl(Stringcode){returnUrlBuilder.fromBaseUrl(this.source.accessToken()).build();}关键解读:this.source.accessToken():source是SinosoftSource.SINOSOFT,调用该枚举实现的accessToken()方法,获取令牌接口的基础 URL(如http://localhost:9999/oauth/access_token)。
UrlBuilder.fromBaseUrl():JustAuth 提供的 URL 构建工具,这里直接构建基础 URL,未拼接code、client-id等参数。
特殊点:与原生 OAuth 流程不同,该方法未拼接code、client_id等必要参数,说明SINOSOFT平台的令牌接口可能不需要这些参数(或通过其他方式传递,如请求头),这是适配该平台的自定义逻辑。
用户信息获取方法:getUserInfo(AuthToken authToken)重写父类方法,用访问令牌换取SINOSOFT平台的用户信息,是整个流程的核心业务解析方法。
@OverrideprotectedAuthUsergetUserInfo(AuthTokenauthToken){//
构建用户信息接口地址(调用自身重写的userInfoUrl()方法)Stringurl=super.userInfoUrl(authToken);//
创建POST请求,访问用户信息接口HttpRequestrequest=HttpUtil.createRequest(Method.POST,url);//
构建请求参数:将accessToken放入请求体(JSON格式)JSONObjectparams=newJSONObject();params.put("token",authToken.getAccessToken());request.body(params.toJSONString());//
执行请求,获取响应体HttpResponseexecute=request.execute();Stringbody=execute.body();//
逐层解析响应体,提取用户信息JSONObjectjsonObject=JSONObject.parseObject(body);JSONObjectresult=jsonObject.getJSONObject("result");JSONObjectuserInfo=result.getJSONObject("userInfo");Stringtoken=result.getString("token");//
更新令牌(该平台返回了新的令牌,替换原有令牌)authToken.setAccessToken(token);//
封装为AuthUser对象返回,存入原始用户信息和更新后的令牌returnAuthUser.builder().rawUserInfo(userInfo).token(authToken).build();}关键解读:请求方式为POST:与令牌接口的GET不同,用户信息接口要求POST请求,适配平台接口规范。
参数传递方式:将令牌放入JSON 请求体中({"token": "xxx"}),而非原生 OAuth 常用的「请求参数」或「请求头」,这是该平台的自定义要求。
多层 JSON 解析:响应体格式为嵌套 JSON(如{"result": {"userInfo": {...}, "token": "new-token"}}),因此需要逐层解析jsonObject → result → userInfo。
令牌更新:该平台在返回用户信息时,同时返回了新的令牌(result.token),因此需要更新AuthToken中的accessToken,供后续业务使用。
rawUserInfo(userInfo):将原始的用户信息 JSON 存入AuthUser,后续业务可从AuthUser.getRawUserInfo()中提取昵称、头像、用户ID等信息(如userInfo.getString("username"))。
用户信息接口地址构建:userInfoUrl(AuthToken authToken)重写父类方法,构建SINOSOFT平台获取用户信息的接口地址。
@OverrideprotectedStringuserInfoUrl(AuthTokenauthToken){returnUrlBuilder.fromBaseUrl(this.source.userInfo()).build();}关键解读:与accessTokenUrl()逻辑一致,直接获取SinosoftSource.SINOSOFT中定义的用户信息接口基础 URL,不拼接额外参数,适配该平台的接口规范。
授权地址构建:authorize(String state)重写父类方法,构建SINOSOFT平台的授权页面地址,用户点击登录时会被重定向到该地址。
@OverridepublicStringauthorize(Stringstate){returnUrlBuilder.fromBaseUrl(this.source.authorize()).queryParam("client_id",this.config.getClientId()).queryParam("redirect_uri",this.config.getRedirectUri()).build();}关键解读:this.source.authorize():获取SINOSOFT平台的授权页面基础 URL(如http://localhost:8089/placedangerous/oauth/login)。
拼接核心参数:通过UrlBuilder拼接client_id和redirect_uri两个参数,最终生成完整授权地址(如http://xxx/oauth/login?client_id=xxxredirect_uri=xxx)。
忽略state参数:方法参数state未被拼接(因 yml 中配置了ignore-check-state: true),符合之前的配置要求,简化了授权流程。
关键亮点与可优化点
亮点(符合项目实际需求)适配性强:完全按照SINOSOFT平台的接口规范(请求方式、参数格式、响应格式)重写核心方法,解决了 JustAuth 原生框架不支持自定义平台的问题。
健壮性高:有完整的异常捕获机制,返回统一的响应格式,避免接口崩溃。
依赖简化:使用Hutool的HttpUtil简化 HTTP 请求操作,减少冗余代码。
配置与代码解耦:通过AuthConfig注入 yml 配置,无需硬编码敏感信息(如client-id)。
可优化点(提升代码质量和扩展性)补充超时时间:将timeout属性应用到HttpRequest中,避免请求超时(如request.timeout(this.timeout))。
增加响应状态码校验:执行 HTTP 请求后,校验响应状态码(如execute.getStatus()是否为
,非 200 直接抛出异常。
补充空指针防护:解析 JSON 时,对result、userInfo等字段做非空判断(如if (jsonObject == null || !jsonObject.containsKey("result"))),避免空指针异常。
封装完整用户信息:将userInfo中的「用户名」「用户ID」「头像」等字段提取出来,封装到AuthUser的对应属性中(如authUser.setUsername(userInfo.getString("username"))),方便后续业务使用。
支持请求头配置:如果平台要求传递「Content-Type: application/json」等请求头,可补充request.header("Content-Type", "application/json")。
四、
总结Oauth2Request是SINOSOFT平台 OAuth 登录的核心处理类,重写了 JustAuth 框架的 6 个核心方法,完成从「授权 → 令牌 → 用户信息」的完整流程。
核心适配点:请求方式(GET/POST)、参数传递格式(URL参数/JSON请求体)、响应解析逻辑(单层/嵌套 JSON),均针对SINOSOFT平台定制。
关键依赖:Hutool(HTTP 请求、JSON 解析)、JustAuth 核心类(AuthToken、AuthUser、UrlBuilder),实现了简化开发和规范封装。
可优化方向:补充超时配置、空指针防护、响应状态码校验,提升代码的健壮性和可维护性。
AuthDefaultRequest你现在看到的是 JustAuth 框架的核心抽象类AuthDefaultRequest(反编译结果),它实现了AuthRequest接口,是所有第三方平台 OAuth 请求处理类的「父类模板」(包括你之前看到的Oauth2Request)。
这个类的
核心价值是封装了 OAuth 登录的通用逻辑和公共方法,定义了必须实现的抽象方法,采用「模板方法模式」简化各平台的自定义实现,让开发者只需关注各平台的差异化逻辑(无需重复编写通用代码)。
我们先
总结整体功能,再分模块拆解核心逻辑,同时对比你之前的Oauth2Request,帮你理解「父类通用逻辑」和「子类差异化实现」的关系。
整体功能
总结模板方法模式:封装 OAuth 登录的通用流程(login()方法),定义两个抽象方法(getAccessToken()、getUserInfo())作为「钩子方法」,要求子类实现平台差异化逻辑。
公共配置初始化:注入AuthConfig(平台配置)、AuthSource(平台接口规范)、AuthStateCache(state 缓存),并做配置合法性校验。
通用工具方法:提供授权地址构建、令牌地址构建、HTTP 请求发送、state 参数处理等通用方法,子类可直接复用或重写。
统一异常处理:封装通用的异常响应逻辑,返回统一格式的AuthResponse。
简单说:这个类做了「所有平台都一样的事」,把「每个平台不一样的事」留给子类(如Oauth2Request)去实现。