企业微信私有化部署对接oauth2.0

1.添加依赖:JustAuth

<dependency>
    <groupId>me.zhyd.oauth</groupId>
    <artifactId>JustAuth</artifactId>
    <version>1.16.6</version>
</dependency>

2.添加 ElephantAuthSource.java

package com.elephant.devops.h5;

import me.zhyd.oauth.config.AuthSource;
import me.zhyd.oauth.request.AuthDefaultRequest;

/**
 * 自定义oauth2.0服务器请求地址
 */
public enum ElephantAuthSource implements AuthSource {
    MengDianE {
        public String authorize() {
            // https://office.impc.com.cn/connect/oauth2/authorize?appid=xxx&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&agentid=AGENTID&state=STATE#wechat_redirect
            return "https://office.impc.com.cn/connect/oauth2/authorize";
        }

        public String accessToken() {
            return "https://office.impc.com.cn/cgi-bin/gettoken";
        }

        public String userInfo() {
            return "https://office.impc.com.cn/cgi-bin/user/getuserinfo";
        }

        public Class<? extends AuthDefaultRequest> getTargetClass() {
            return AuthMengDianRequest.class;
        }
    }
}

3.添加 AuthMengDianRequest.java

/**
 * 企业微信:蒙电E联授权获取用户手机号
 */
@Slf4j
public class AuthMengDianRequest extends AbstractAuthWeChatEnterpriseRequest {

    public AuthMengDianRequest(AuthConfig config) {
        super(config, ElephantAuthSource.MengDianE);
    }

    public AuthMengDianRequest(AuthConfig config, AuthStateCache authStateCache) {
        super(config, ElephantAuthSource.MengDianE, authStateCache);
    }

    public String authorize(String state) {
        return UrlBuilder.fromBaseUrl(this.source.authorize())
                .queryParam("appid", this.config.getClientId())
                .queryParam("agentid", this.config.getAgentId())
                .queryParam("redirect_uri", GlobalAuthUtils.urlEncode(this.config.getRedirectUri()))
                .queryParam("response_type", "code")
                .queryParam("scope", this.getScopes(",", false, AuthScopeUtils.getDefaultScopes(AuthWeChatEnterpriseWebScope.values())))
                .queryParam("state", this.getRealState(state).concat("#wechat_redirect")).build();
    }

    @Override
    public AuthResponse login(AuthCallback authCallback) {
        try {
            //this.checkCode(authCallback);
            //{"accessToken":"...","expireIn":7200,"refreshTokenExpireIn":0,"code":"...","snapshotUser":false}
            AuthToken authToken = this.getAccessToken(authCallback);
            //手机号=username
            AuthUser user = this.getUserInfo(authToken);
            return AuthResponse.builder().code(AuthResponseStatus.SUCCESS.getCode()).data(user).build();
        } catch (Exception var4) {
            Exception e = var4;
            Log.error("Failed to login with oauth authorization.", e);
            return this.responseError(e);
        }
    }

    protected AuthToken getAccessToken(AuthCallback authCallback) {
        String accessTokenUrl = this.accessTokenUrl(authCallback.getCode());
        log.info(">>>> accessTokenUrl: {}", accessTokenUrl);
        String response = this.doGetAuthorizationCode(accessTokenUrl);
        log.info(">>>> response: {}", response);
        JSONObject object = this.checkResponse(response);
        return AuthToken.builder().accessToken(object.getString("access_token")).expireIn(object.getIntValue("expires_in")).code(authCallback.getCode()).build();
    }

    @Override
    protected AuthUser getUserInfo(AuthToken authToken) {
        String response = this.doGetUserInfo(authToken);
        log.info(">>>> response = {}", response);
        // {"UserId":"MD_chenhong","DeviceId":"xxx","errcode":0,"errmsg":"ok","usertype":5}
        JSONObject object = this.checkResponse(response);
        if (!object.containsKey("UserId")) {
            throw new AuthException(AuthResponseStatus.UNIDENTIFIED_PLATFORM, this.source);
        } else {
            String userId = object.getString("UserId");
            /* {"errcode":0,"gender":"1","is_leader_in_dept":[0],"direct_leader":[],"userid":"MD_chenhong",
                "english_name":"","enable":1,"qr_code":"https://wwlocal.qq.com/wework_admin/userQRCode?lvc=vc78d250e697f27eba",
                "department":[39246],"email":"","order":[4096],"isleader":0,"mobile":"13580575781","errmsg":"ok","telephone":"",
                "positions":[""],"avatar":"","hide_mobile":0,"country_code":"86","biz_mail_alias":[],"name":"陈鸿","extattr":{"attrs":[]},"position":"",
                "external_profile":{"external_attr":[],"external_corp_name":"内蒙古电力集团"},"status":1}*/
            JSONObject userDetail = this.getUserDetail(authToken.getAccessToken(), userId, null);
            return AuthUser.builder().rawUserInfo(userDetail)
                    .nickname(userDetail.getString("name")).avatar(userDetail.getString("avatar"))
                    .username(userDetail.getString("mobile")).uuid(userId)
                    .gender(AuthUserGender.getWechatRealGender(userDetail.getString("gender")))
                    .token(authToken).source(this.source.toString()).build();
        }
    }

    protected String doGetUserInfo(AuthToken authToken) {
        //https://office.impc.com.cn/cgi-bin/user/getuserinfo?access_token=xxxxx&code=xxx
        String userInfoUrl = this.userInfoUrl(authToken);
        log.info(">>> userInfoUrl = {}", userInfoUrl);
        return HttpUtil.get(userInfoUrl);
        //http请求经常超时有bug
        //return (new HttpUtils(this.config.getHttpConfig())).get(userInfoUrl).getBody();
    }

    AuthResponse responseError(Exception e) {
        int errorCode = AuthResponseStatus.FAILURE.getCode();
        String errorMsg = e.getMessage();
        if (e instanceof AuthException) {
            AuthException authException = (AuthException)e;
            errorCode = authException.getErrorCode();
            if (StringUtils.isNotEmpty(authException.getErrorMsg())) {
                errorMsg = authException.getErrorMsg();
            }
        }
        return AuthResponse.builder().code(errorCode).msg(errorMsg).build();
    }

    private JSONObject checkResponse(String response) {
        JSONObject object = JSONObject.parseObject(response);
        if (object.containsKey("errcode") && object.getIntValue("errcode") != 0) {
            throw new AuthException(object.getString("errmsg"), this.source);
        } else {
            return object;
        }
    }

    private JSONObject getUserDetail(String accessToken, String userId, String userTicket) {
        String userInfoUrl = UrlBuilder.fromBaseUrl("https://office.impc.com.cn/cgi-bin/user/get").queryParam("access_token", accessToken).queryParam("userid", userId).build();
        String userInfoResponse = (new HttpUtils(this.config.getHttpConfig())).get(userInfoUrl).getBody();
        JSONObject userInfo = this.checkResponse(userInfoResponse);
        if (StringUtils.isNotEmpty(userTicket)) {
            String userDetailUrl = UrlBuilder.fromBaseUrl("https://office.impc.com.cn/cgi-bin/auth/getuserdetail").queryParam("access_token", accessToken).build();
            JSONObject param = new JSONObject();
            param.put("user_ticket", userTicket);
            String userDetailResponse = (new HttpUtils(this.config.getHttpConfig())).post(userDetailUrl, param.toJSONString()).getBody();
            JSONObject userDetail = this.checkResponse(userDetailResponse);
            userInfo.putAll(userDetail);
        }
        return userInfo;
    }
}

4.添加 Oauth2Controller.java

@RestController
@RequestMapping("/api/pub/oauth2")
@Api(value = "Oauth2Controller ", tags = "蒙电E家oauth2")
@Slf4j
public class Oauth2Controller extends BaseController {

    @Autowired
    private AuthService authService;

    /**
     * localhost:7061/api/pub/oauth2/render
     * 跳转进入:
     * https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxx&agentid=10xxx&redirect_uri=https://office.impc.com.cn/cgi-bin/gettoken&response_type=code&scope=snsapi_base&state=xxxx#wechat_redirect
     * https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxx&agentid=10xxx&redirect_uri=https://office.impc.com.cn&response_type=code&scope=snsapi_base&state=xxxx#wechat_redirect
     * @param response
     * @throws IOException
     */
    @GetMapping("/render")
    public void renderAuth(HttpServletResponse response) throws IOException {
        AuthRequest authRequest = getAuthRequest();
        response.sendRedirect(authRequest.authorize(AuthStateUtils.createState()));
    }

    /**
     * 查询 state
     * localhost:7061/api/pub/oauth2/getState
     * @return
     */
    @GetMapping("/getState")
    public Result getState() {
        AuthRequest authRequest = getAuthRequest();
        String state = AuthStateUtils.createState();
        String url = authRequest.authorize(state);
        log.debug("url = {}", url);
        return Result.success(state);
    }

    /**
     * localhost:7061/api/pub/oauth2/callback?code=xxx&state=xxx
     * @param callback
     * @return
     */
    @GetMapping("/callback")
    public Result<AuthVO> callback(AuthCallback callback) {
        AuthRequest authRequest = getAuthRequest();
        try {
            AuthResponse response = authRequest.login(callback);
            log.info(">>>> response = {}", JSONUtil.toJsonStr(response));
            int code = response.getCode();
            if(code == 2000) {
                AuthUser data = (AuthUser) response.getData();
                String phone = data.getUsername();
                AuthVO authVO = authService.loginByPhone(phone);
                if(authVO != null) {
                    return Result.success(authVO);
                }else {
                    AuthVO bean = new AuthVO();
                    bean.setToken("-1");
                    return Result.success(bean);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return Result.fail("500", "系统异常");
    }

    private AuthRequest getAuthRequest() {
        return new AuthMengDianRequest(AuthConfig.builder()
                .clientId("xxxx")
                .clientSecret("xxxxxxx")
                .redirectUri("https://office.impc.com.cn")
                .agentId("xxxxx")
                .build());
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/576645.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

12.Blender 界面介绍(上)及物体基础编辑操作

设置语言 首先在菜单栏打开编辑-Preferences-界面-翻译&#xff0c;可以修改语言 这里使用的是Steam上下载的4.1版本 工具栏 左边的工具栏&#xff0c;按T就会出现&#xff0c;再按T就会隐藏 右边的工具栏是按N&#xff0c;按N显示&#xff0c;再按N隐藏 旋转画面 长按鼠…

C语言面试题之相交链表

相交链表 实例要求 1、给定两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。2、如果两个链表不存在相交节点&#xff0c;返回 null 。示例&#xff1a; 实例分析 可以使用两种方法&#xff1a;哈希表方法和双指针方法。哈希表方法…

Golang基础7-并发编程

并发编程 https://www.cnblogs.com/Survivalist/p/11527949.html 进程和线程、协程的区别_线程协程进程的区别-CSDN博客 Golang中的并发编程是一个重点&#xff0c;我们要了解Golang中的并发Goroutine因此需要先理解进程、线程、之后再理解协程。 进程&#xff1a;操作系统进…

某翻译平台翻译接口逆向之webpack学习

逆向网址 aHR0cHM6Ly9mYW55aS55b3VkYW8uY29tLw 逆向链接 aHR0cHM6Ly9mYW55aS55b3VkYW8uY29tLyMv 逆向接口 aHR0cHM6Ly9kaWN0LnlvdWRhby5jb20vd2VidHJhbnNsYXRl 逆向过程 请求方式 POST 逆向参数 sign c168e4cb76169e90f82d28118dbd24d2 接口请求结果解密 过程分析 根据XHR…

免费获取!遗传算法+多目标规划算法+自适应神经模糊系统程序代码!

前言 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世纪70年代提出&#xff0c;该算法是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型&#xff0c;通过数学的方式&#xff0c;将问题的求解过程转…

全国省级金融发展水平数据集(2000-2022年)

01、数据简介 金融发展水平是一个国家或地区经济实力和国际竞争力的重要体现。它反映了金融体系的成熟程度和发展水平&#xff0c;是衡量一个国家或地区经济发展质量的重要指标。金融发展水平的提高&#xff0c;意味着金融体系能够更好地服务实体经济&#xff0c;推动经济增长…

3.7设计模式——Observer 观察者模式(行为型)

意图 定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于他的对象都得到通知并被自动更新。 结构 Subject&#xff08;目标&#xff09;知道它的观察者&#xff0c;可以有任意多个观察者观察同一个目标&#xff0c;提供注册和删…

模块三:二分——153.寻找旋转排序数组中的最小值

文章目录 题目描述算法原理解法一&#xff1a;暴力查找解法二&#xff1a;二分查找疑问 代码实现解法一&#xff1a;暴力查找解法二&#xff1a;CJava 题目描述 题目链接&#xff1a;153.寻找旋转排序数组中的最小值 根据题目的要求时间复杂度为O(log N)可知需要使用二分查找…

电子负载仪的远端控制

前言 最近研究了电子负载仪的远端控制&#xff08;区别于前面板控制&#xff09;&#xff0c;主要是用于程序控制&#xff0c;避免繁琐复杂的人工控制&#xff0c;举了南京嘉拓和艾维泰科的例子。 有纰漏请指出&#xff0c;转载请说明。 学习交流请发邮件 1280253714qq.com …

基于JavaWEB的学生考勤管理系统(含论文)

本系统是用Java语言写的&#xff0c;基于JavaWEB的学生考勤管理系统 主要有三大模块&#xff0c;学生&#xff0c;教师和管理员模块&#xff0c;功能如下&#xff1a; 学生模块 教师模块&#xff1a; 管理员模块

深入了解Semaphore、CountDownLatch等实用工具的用法

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…

4月26(信息差)

&#x1f30d; 1170万台 华为跃升重回首位&#xff01;苹果跌至第五位 &#x1f384;工业软件大事件 —— OGG 1.0 发布&#xff0c;华为贡献全部源代码 ✨ 苹果发布 OpenELM&#xff1a;专为在设备端运行而设计的小型开源 AI 模型 1.FisheyeDetNet&#xff1a;首个基于鱼眼相…

LED驱动模块RSC6218A 5W-18W迷你高效驱动电源应用-REASUNOS(瑞森半导体)

一、LED驱动模块RSC6218A REASUNOS(瑞森半导体)通过持续投入研发&#xff0c;提升LLC应用技术&#xff0c;集成控制芯片与功率转换&#xff0c;成功推出新一代产品RSC6218A WSOP-16&#xff0c;延续瑞森LLC拓扑方案&#xff0c;时机趋势完全迎合我国双碳政策&#xff0c;电气特…

【Web】DASCTF X GFCTF 2024|四月开启第一局 题解(全)

目录 EasySignin cool_index SuiteCRM web1234 法一、条件竞争(没成功) 法二、session反序列化 EasySignin 先随便注册个账号登录&#xff0c;然后拿bp抓包改密码(username改成admin) 然后admin / 1234567登录 康好康的图片功能可以打SSRF&#xff0c;不能直接读本地文…

Docker网络模式与cgroup资源控制

前言 在 Docker 中&#xff0c;网络模式和 cgroup 资源控制作为关键功能&#xff0c;对于容器的性能优化和资源管理起着至关重要的作用。本文将介绍 Docker 的网络模式和cgroup资源控制&#xff0c;探讨不同网络模式的特点以及如何利用 cgroup 资源控制机制来有效管理容器的资…

不使用加减运算符实现整数加和减

文章目录 进位 进位 加粗 最近想出了不适用运算符实现加与减 首先按位与找出的是需不需要进位 按位与是两边同时为1,则为1,那么如果两边同时为1的话,是不是就该进位?所以我们用按位与来判断是否需要进位 然后再按位异或找出不同的位数 按位异或是两边不相等,也就是1 和 0的时…

SpringBoot源码阅读2-自动配置

SpringBoot源码阅读2-自动配置 在传统的Spring应用中&#xff0c;开发者需要手动配置一系列Web应用的核心组件&#xff0c;例如DispatcherServlet用于处理请求分发、ViewResolver用于视图解析、CharacterEncodingFilter用于字符编码过滤等。 然而在SpringBoot中只要引入了spr…

力扣HOT100 - 994. 腐烂的橘子

解题思路&#xff1a; 因为要记录轮数&#xff08;分钟数&#xff09;&#xff0c;所以不能一口气遍历到底&#xff0c;所以不能用深搜&#xff08;bfs&#xff09;&#xff0c;而要用广搜&#xff08;bfs&#xff0c;层序遍历&#xff09;。 先记录下新鲜橘子数&#xff0c;…

github+PicGo+obsidian来作为你的免费高效可靠图床吧

前提 一直以来 博客的图床问题都是个大问题 ,如何找到一个 可靠并且 方便的搭建方式 非常重要 今天介绍一种 githubpicGoobsidian的搭建方式 准备github库 生成个人github token 找到个人 设置 生成一个新token 或者已经有的直接用 新生成的token 需要记录下来 这可能是你最后…

在若依Ruoyi-Vue中集成mybatisplus实现mybatis增强

本文相关视频&#xff1a;https://www.bilibili.com/video/BV1Fi4y1q74p?p50&vd_source2894aa0e46c09ba98269f266128b6c6e 若依&#xff08;Ruoyi&#xff09;作为一款优秀的基于Spring Boot和Vue.js的企业级后台管理系统&#xff0c;其良好的架构设计和丰富的功能组件深…
最新文章